home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-11 | 176.1 KB | 5,647 lines | [TEXT/MPS ] |
- /*------------------------------------------------------------------------------
-
- File: SoundEditor.cpp
-
- Written by: Steve Smith, Andrey Dolgachev, and Troy Gaul
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- Description: The Sound Editor is a simple record/playback part using the
- Macintosh Sound Mgr. The part demonstrates handling of
- simple content, support for multiple content "kinds",
- reading/writing data from the Clipboard, use of library
- resources, and a movable process modal dialog. The part is
- based on SamplePart which should make it easier to
- understand.
-
- Demonstrates: The following recipes were used in implementing the
- SoundEditor:
- 1. Open
- 2. Adding A Display Frame
- 3. Adding A Facet
- 4. Part Drawing
- 5. Refcounting Geometry
- 6. ViewTypes & Presentations
- 7. Display Frame 'ternalization
- 8. Part Init & Externalization
- 9. Part Init & partWrapper
- 10. Part Storage Model
- 11. Persistent Reference
- 12. RefCounting
- 13. Storage Unit
- 14. Activation
- 15. Basic Event Handling
- 16. Menus
- 17. Windows & Dialogs
- 18. Exception Handling
- 19. Memory Manager
- 20. Using Resources
- 21. Clipboard Part 1 & 2
- 22. Dropping Non-OpenDoc Files
- 23. Multiple Kind Support
-
-
- Notes: • For methods where it is necessary to call the parent class
- implementation, the calls are made from the SOM class. See
- som_SamplePart.cpp and the Class Reference to know whether
- you need to call the parent class from any method.
-
-
- ------------------------------------------------------------------------------*/
-
- // -- Compiler/Preprocessor Switches --
-
- #ifndef _COMPILERDEFS_
- #include "CompDefs.h"
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _EXCEPT_
- // Exceptions define several important macros (eg. CHECKENV)
- // which are used in the SOM method dispatch glue. If Except.h
- // is not included early enough, exceptions may not be thrown
- // correctly when returning from a SOM method with the "ev" parameter set.
- #include <Except.h>
- #endif
-
- // -- SoundEditor Includes --
-
- #ifndef _SOUNDEDITOR_
- #include "SoundEditor.h"
- #endif
-
- #ifndef _SOUNDEDITORDEF_
- #include "SoundEditorDef.h"
- #endif
-
- #ifndef _SOUNDEDITORGLOBALS_
- #include "SoundEditorGlobals.h"
- #endif
-
- #ifndef _SOUNDEDITORUTILS_
- #include "SoundEditorUtils.h"
- #endif
-
- #ifndef _SOUNDHANDLING_
- #include "SoundHandling.h"
- #endif
-
- #ifndef SOM_som_SESettingsExtension_xh
- #include "som_SESettingsExtension.xh"
- #endif
-
- #ifndef SOM_SoundEditorSI_xih
- #include "som_SoundEditorSI.xh"
- #endif
-
- #ifndef _SAMPLECOLLECTIONS_
- #include "SampleCollections.h"
- #endif
-
- // -- OpenDoc Includes --
-
- #ifndef SOM_ODArbitrator_xh
- #include <Arbitrat.xh>
- #endif
-
- #ifndef SOM_ODCanvas_xh
- #include <Canvas.xh>
- #endif
-
- #ifndef SOM_ODClipboard_xh
- #include <Clipbd.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Commands_defined
- #include <CmdDefs.xh>
- #endif
-
- #ifndef SOM_ODDispatcher_xh
- #include <Disptch.xh>
- #endif
-
- #ifndef SOM_ODDraft_xh
- #include <Draft.xh>
- #endif
-
- #ifndef SOM_ODFacet_xh
- #include <Facet.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Foci_defined
- #include <Foci.xh>
- #endif
-
- #ifndef SOM_ODFocusSet_xh
- #include <FocusSet.xh>
- #endif
-
- #ifndef SOM_ODFrame_xh
- #include <Frame.xh>
- #endif
-
- #ifndef SOM_ODMenuBar_xh
- #include <MenuBar.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef _ODTYPES_
- #include <ODTypes.h>
- #endif
-
- #ifndef SOM_ODPart_xh
- #include <Part.xh>
- #endif
-
- #ifndef SOM_ODShape_xh
- #include <Shape.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdDefs_defined
- #include <StdDefs.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StandardExtensions_defined
- #include <StdExts.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODStorageUnitView_xh
- #include <SUView.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- #ifndef SOM_ODTranslation_xh
- #include <Translt.xh>
- #endif
-
- #ifndef SOM_ODTypeList_xh
- #include <TypeList.xh>
- #endif
-
- #ifndef SOM_ODWindow_xh
- #include <Window.xh>
- #endif
-
- #ifndef SOM_ODWindowState_xh
- #include <WinStat.xh>
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _BNDNSUTL_
- #include <BndNSUtl.h>
- #endif
-
- #ifndef _FOCUSLIB_
- #include <FocusLib.h>
- #endif
-
- #ifndef _INFOUTIL_
- #include <InfoUtil.h>
- #endif
-
- #ifndef _ISOSTR_
- #include <ISOStr.h>
- #endif
-
- #ifndef _ITEXT_
- #include <IText.h>
- #endif
-
- #ifndef _ODMEMORY_
- #include <ODMemory.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef _STDTYPIO_
- #include <StdTypIO.h>
- #endif
-
- #ifndef _STORUTIL_
- #include <StorUtil.h>
- #endif
-
- #ifndef _TEMPITER_
- #include <TempIter.h>
- #endif
-
- #ifndef _TEMPOBJ_
- #include <TempObj.h>
- #endif
-
- #ifndef _USERSRCM_
- #include <UseRsrcM.h>
- #endif
-
- #ifndef _WINUTILS_
- #include <WinUtils.h>
- #endif
-
- // -- Macintosh Includes --
-
- #ifndef __DIALOGS__
- #include <Dialogs.h>
- #endif
-
- #ifndef __DRAG__
- #include <Drag.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __GXMATH__
- #include <GXMath.h>
- #endif
-
- #ifndef __ICONS__
- #include <Icons.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __QUICKDRAW__
- #include <Quickdraw.h>
- #endif
-
-
- #pragma segment SoundEditor
-
- //==============================================================================
- #pragma mark • Multiple Kind Utility Functions •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Function: IsKindSupported
- // Origin: SoundEditor
- //
- // Description: Return a boolean result indicating whether the given kind
- // token is supported by SoundEditor.
- //------------------------------------------------------------------------------
-
- static ODBoolean IsKindSupported( Environment* ev,
- ODTypeToken token )
- {
- return (token == gGlobals->fNativeData
- || token == gGlobals->fMacSndData);
- }
-
- //------------------------------------------------------------------------------
- // Function: GetKindFromToken
- // Origin: SoundEditor
- //
- // Description: Given a token, return the type that it corresponds to.
- //------------------------------------------------------------------------------
-
- static ODType GetKindFromToken( Environment* ev,
- ODTypeToken token)
- {
- WASSERT(IsKindSupported(ev, token));
-
- if ( token == gGlobals->fNativeData )
- return kSoundEditorKind;
-
- else if ( token == gGlobals->fMacSndData )
- return gGlobals->fSndDataKind;
-
- else
- return kODNULL;
- }
-
- //------------------------------------------------------------------------------
- // Function: SetPreferredKind
- // Origin: SoundEditor
- //
- // Description: This function will set the preferred kind property of the
- // given storage unit to the given type.
- //------------------------------------------------------------------------------
-
- static void SetPreferredKind( Environment* ev,
- ODStorageUnit* storageUnit,
- ODType kind )
- {
- TRY
- if ( kind == kODNULL )
- ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
- else
- ODSetISOStrProp(ev, storageUnit, kODPropPreferredKind, kODISOStr, kind);
- CATCH_ALL
- // Remove the property and value if something went wrong.
- ODSURemoveProperty(ev, storageUnit, kODPropPreferredKind);
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Function: GetKindToInternalize
- // Origin: SoundEditor
- //
- // Description: Returns a token representing the kind of data that should be
- // internalized from the given storage unit.
- //------------------------------------------------------------------------------
-
- static ODTypeToken GetKindToInternalize( Environment* ev,
- ODSession* session,
- ODStorageUnit* storageUnit )
- {
- // This should become a token representing the kind of data that should be
- // internalized from the given storage unit.
- ODTypeToken kindToUse = kODNullTypeToken;
-
- TempODISOStr docPrefKindStr = ODGetISOStrProp(ev, storageUnit, kODPropPreferredKind,
- kODISOStr, kODNULL, kODNULL);
-
- ODTypeToken docPrefKind = kODNullTypeToken;
- if (docPrefKindStr != kODNULL)
- docPrefKind = session->Tokenize(ev, docPrefKindStr);
-
- // If the data has a preferred kind, see if we can use it.
- if ( docPrefKind != kODNullTypeToken && IsKindSupported(ev, docPrefKind)
- && storageUnit->Exists(ev, kODPropContents, GetKindFromToken(ev, docPrefKind), 0) )
- {
- kindToUse = docPrefKind;
- }
-
- // If there is not document-preferred kind, we don't support it, or it wasn't found,
- // find the first value (the one with highest fidelity) that we understand.
- if (kindToUse == kODNullTypeToken)
- {
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosAll);
- ODULong numValues = storageUnit->CountValues(ev);
-
- for (ODULong index = 1; index <= numValues; index++)
- {
- // Index from n to 1 through the values -- lowest fidelity to highest.
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL,
- index, kODPosUndefined);
- TempODValueType value = storageUnit->GetType(ev);
-
- ODTypeToken valueToken = session->Tokenize(ev, value);
- if ( IsKindSupported(ev, valueToken) )
- {
- kindToUse = valueToken;
- break;
- }
- }
- }
-
- return kindToUse;
- }
-
-
- //==============================================================================
- // SoundEditor
- //==============================================================================
-
- //==============================================================================
- #pragma mark • Construction and Destruction •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: Constructor
- // Origin: SoundEditor
- //
- // Description: This is the C++ class constructor.
- //
- // Warnings: You are not allowed to throw an exception from this method.
- //------------------------------------------------------------------------------
-
- SoundEditor::SoundEditor()
- {
- SOM_Trace("SoundEditor","Constructor");
-
- fDisplayFrames = kODNULL;
- fSettingsExtension = kODNULL;
- fSemIntf = kODNULL;
-
- fSession = kODNULL;
- fSelf = kODNULL;
-
- fDirty = kODFalse;
- fReadOnlyStorage = kODFalse;
- fPreferredKind = kODNullTypeToken;
-
- fPlayer = kODNULL;
- fRecorder = kODNULL;
-
- fMenuSavedResFile = -1;
-
- fRecordingQuality = siGoodQuality;
- fCurrentTime = 0;
-
- fMaxMemory = 1024000;
- fMaxSeconds = 0;
- fSecsRecorded = 0;
- fUnknownSound = kODTrue;
- }
-
- //------------------------------------------------------------------------------
- // Method: Destructor
- // Origin: SoundEditor
- //
- // Description: This is the C++ class destructor.
- //
- // Warnings: You are not allowed to throw an exception from this method.
- //------------------------------------------------------------------------------
-
- SoundEditor::~SoundEditor()
- {
- SOM_Trace("SoundEditor","Destructor");
- }
-
- //==============================================================================
- #pragma mark • Initialization •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: InitPart
- // Origin: ODPart
- //
- // Description: This method is called when a new instance of this part is being
- // created. The part should prepare itself to run.
- //
- // Parent: The part's parent class was called before this method was
- // dispatched to (see som_SamplePart.cpp).
- //
- // Warning: It is not appropriate to require user interaction while
- // stationery is being created. Do not present the user with error
- // dialogs or splash screens from this method.
- //------------------------------------------------------------------------------
-
- void SoundEditor::InitPart( Environment* ev,
- ODStorageUnit* storageUnit,
- ODPart* partWrapper )
- {
- SOM_Trace("SoundEditor","InitPart");
-
- // To allow editor swapping (translation) at runtime, OpenDoc requires
- // that we pass in a "reference" to ourselves when interacting with the
- // API (e.g. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
- // The "partWrapper" passed to us here and in InitPartFromStorage is the
- // "reference" OpenDoc is asking us to use.
- fSelf = partWrapper;
-
- // We are being created, either as part of generating stationery or
- // by some editor instantiating the part, so the destination storage
- // must be writeable.
- fReadOnlyStorage = kODFalse;
-
- // Call the common initialization code to get set up.
- this->Initialize(ev);
-
- // Since we're making stationery, we will select the default kind
- // as the preferred kind.
- fPreferredKind = gGlobals->fNativeData;
-
- // Since we have just been created, our state/content info has
- // never been written out, so setting our "dirty" flag will
- // give us a chance to do that.
- this->SetDirty(ev);
-
- // If an exception is thrown, clean up will occur in the destructor
- // which will be called shortly after the error is raised.
- }
-
- //------------------------------------------------------------------------------
- // Method: InitPartFromStorage
- // Origin: ODPart
- //
- // Description: This method is called when a document/stationery is being opened
- // or when the part is internalized by its containing part. The
- // part should merely read in the saved state/content and
- // initialize itself. The part must not alter its storage unit;
- // otherwise, the "Save" menu item becomes enabled without the user
- // actually having made a change to the document.
- //
- // Parent: The part's parent class was called before this method was
- // dispatched to (see som_SamplePart.cpp).
- //------------------------------------------------------------------------------
-
- void SoundEditor::InitPartFromStorage( Environment* ev,
- ODStorageUnit* storageUnit,
- ODPart* partWrapper )
- {
- SOM_Trace("SoundEditor","InitPartFromStorage");
-
- // To allow editor swapping (translation) at runtime, OpenDoc requires
- // that we pass in a "reference" to ourselves when interacting with the
- // API (e.g. WindowState::RegisterWindow(), Dispatcher::RegisterIdle, etc).
- // The "partWrapper" passed to us here and in InitPart is the
- // "reference" OpenDoc is asking us to use.
- fSelf = partWrapper;
-
- // Are we being opened from a read-only draft? If so, we cannot
- // write anything back out to our storage unit.
- fReadOnlyStorage = (ODGetDraft(ev,storageUnit)->GetPermissions(ev)
- < kODDPSharedWrite);
-
- // Call the common initialization code to get set up.
- this->Initialize(ev);
-
- // Read in the state the part was in when it was last Externalized.
- // This allows the part to present the same "environment" the user
- // had the part set up in the last time it was edited.
- this->InternalizeStateInfo(ev, storageUnit);
-
- // Read in the content annotation.
- this->InternalizeAnnotation(ev, storageUnit);
-
- // Read in the contents for your part editor.
- this->InternalizeContent(ev, storageUnit);
-
- // If an exception is thrown, clean up will occur in the destructor
- // which will be called shortly after the error is raised.
- }
-
- //------------------------------------------------------------------------------
- // Method: Initialize
- // Origin: SoundEditor
- //
- // Description: This method is called during the initialization of the part. The
- // method is used to initialize all fields of the part and to
- // convert ISO string types to tokens for faster comparisons
- // throughout the code.
- //
- // If an exception is thrown in this method, it wil be propogated
- // back to OpenDoc which will call our ReleaseAll() method and the
- // class destructor. All memory allocated here will be cleaned up
- // in the ReleaseAll() method.
- //------------------------------------------------------------------------------
-
- void SoundEditor::Initialize( Environment* ev )
- {
- SOM_Trace("SoundEditor","Initialize");
-
- // Grab a reference to the Session object. This is merely for
- // convenience.
- fSession = ODGetSession(ev, fSelf);
-
- // Create a list to keep track of the frames we are being
- // displayed in. Also used for maintenance (i.e., Purging memory).
- fDisplayFrames = new CList;
-
- // Create the CPlayer and CRecorder helper classes to handle
- // recording and playing sound
- fPlayer = new CPlayer;
- fRecorder = new CRecorder;
-
- // First check to see if the library's global variables have
- // been initialized (meaning another part instantiation is already
- // running).
-
- if ( gGlobalsUsageCount == 0 )
- {
- // Create our globals space. We store the globals in a struct so
- // that we can put them in temp mem. Otherwise, CFM loads the globals
- // with the data fragment of a CFM library in the application heap.
- gGlobals = new SoundEditorGlobals;
-
- // We will be using the following foci (shared resources) in this
- // part. For convenience, we tokenize the values here and store
- // them for equivalence tests in the activation methods.
- gGlobals->fSelectionFocus = fSession->Tokenize(ev, kODSelectionFocus);
- gGlobals->fMenuFocus = fSession->Tokenize(ev, kODMenuFocus);
- gGlobals->fKeyFocus = fSession->Tokenize(ev, kODKeyFocus);
- gGlobals->fModalFocus = fSession->Tokenize(ev, kODModalFocus);
- gGlobals->fSoundInFocus = fSession->Tokenize(ev, kSoundInFocus);
- gGlobals->fSoundOutFocus = fSession->Tokenize(ev, kSoundOutFocus);
- gGlobals->fClipboardFocus = fSession->Tokenize(ev, kODClipboardFocus);
-
- // Also for convenience, we tokenize our part's main presentation
- // and the standard view types.
- gGlobals->fControlsPresentation = fSession->Tokenize(ev, kControlsPresentation);
-
- gGlobals->fFrameView = fSession->Tokenize(ev, kODViewAsFrame);
- gGlobals->fLargeIconView = fSession->Tokenize(ev, kODViewAsLargeIcon);
- gGlobals->fSmallIconView = fSession->Tokenize(ev, kODViewAsSmallIcon);
- gGlobals->fThumbnailView = fSession->Tokenize(ev, kODViewAsThumbnail);
-
- // The Sound Editor defines the "Sound in" and "Sound out" ports as
- // shared resources. To allow sharing of these resources, we register them
- // with the Arbitrator. NOTE: By passing kODNULL as the focus module in
- // the RegisterFocus call, we are telling OpenDoc to use the default
- // single-owner type of focus module.
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
- if ( !arbitrator->IsFocusRegistered(ev, gGlobals->fSoundInFocus) )
- arbitrator->RegisterFocus(ev, gGlobals->fSoundInFocus, kODNULL);
- if ( !arbitrator->IsFocusRegistered(ev, gGlobals->fSoundOutFocus) )
- arbitrator->RegisterFocus(ev, gGlobals->fSoundOutFocus, kODNULL);
-
- // Lastly, we will package the following foci
- // so that we can request the "set" at activation time.
- gGlobals->fUIFocusSet = arbitrator->CreateFocusSet(ev);
- gGlobals->fUIFocusSet->Add(ev, gGlobals->fMenuFocus);
- gGlobals->fUIFocusSet->Add(ev, gGlobals->fKeyFocus);
- gGlobals->fUIFocusSet->Add(ev, gGlobals->fSelectionFocus);
-
- // The part supports importing sound files and data, so we must
- // get the value types OpenDoc associates with each. To do
- // this, we must call the Translation object.
- gGlobals->fSndDataKind = fSession->GetTranslation(ev)->
- GetISOTypeFromPlatformType(ev, 'snd ', kODPlatformDataType);
-
- gGlobals->fSndFileKind = fSession->GetTranslation(ev)->
- GetISOTypeFromPlatformType(ev, 'sfil', kODPlatformFileType);
-
- gGlobals->fAppleHFSFlavor = fSession->GetTranslation(ev)->
- GetISOTypeFromPlatformType(ev, 'hfs ', kODPlatformDataType);
-
- // Tokenize the content value types that our part supports so
- // we can more easily support writing data in the preferred kind.
- gGlobals->fNativeData = fSession->Tokenize(ev, kSoundEditorKind);
- gGlobals->fMacSndData = fSession->Tokenize(ev, gGlobals->fSndDataKind);
- gGlobals->fMacSndFile = fSession->Tokenize(ev, gGlobals->fSndFileKind);
-
- // Add our resource-based menus and register all the editor specific
- // command numbers.
- this->BuildMenuBar(ev);
-
- // Determine what Script/Language the part is localized for.
- // This is important/necessary for creating OpenDoc's text objects.
- GetEditorScriptLanguage(ev, &gGlobals->fEditorsScript, &gGlobals->fEditorsLanguage);
-
- // The first client of the global variables is running.
- gGlobalsUsageCount = 1;
- }
- else
- // If the globals have been initialized, we keep a "usage" count so that
- // we can null out the global variables when we are finished using them.
- {
- gGlobalsUsageCount++;
- }
- }
-
- //==============================================================================
- #pragma mark • Storage •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: Release
- // Origin: ODPart
- //
- // Description: This method is called each time an object releases a reference
- // to the part. If the refcount falls to 0, the part should
- // release the fSelf part reference.
- //
- // Parent: The part's parent class was called before this method was
- // dispatched to (see som_SamplePart.cpp).
- //
- // Warning: If the part releases any other object when the refcount falls to
- // zero, it will need to override the IncrementRefCount method so
- // that the object can be referenced again if the parts refcount
- // should be incremented before it is deleted.
- //------------------------------------------------------------------------------
-
- void SoundEditor::Release( Environment* ev )
- {
- SOM_Trace("SoundEditor","Release");
-
- if (fSelf->GetRefCount(ev) == 0)
- ODGetDraft(ev, fSelf)->ReleasePart(ev, fSelf);
- }
-
- //------------------------------------------------------------------------------
- // Method: ReleaseAll
- // Origin: ODPart
- //
- // Description: This method is called just prior to the part being deleted by
- // the Draft. The part must release all references to all
- // refcounted objects it has stored internally; not doing so, will
- // cause an "invalid ref count" exception/error at some later time.
- //
- // Parent: The part's parent class will be called after this method
- // returns (see som_SamplePart.cpp).
- //------------------------------------------------------------------------------
-
- void SoundEditor::ReleaseAll( Environment* ev )
- {
- SOM_Trace("SoundEditor","ReleaseAll");
-
- // Release our extensions. Note: we can't use ODReleaseObject or
- // ODFinalReleaseObject here because they null out the field before the
- // call to Release, but we need the field intact when ReleaseExtension is
- // called back upon the last reference being released.
- ODRelease(ev, fSettingsExtension);
- ODRelease(ev, fSemIntf);
-
- // Delete the player and recorder helper objects
- ODDeleteObject(fPlayer);
- ODDeleteObject(fRecorder);
-
- // If the last part instance using the globals is released,
- // we need to delete the globals.
- if ( --gGlobalsUsageCount == 0 )
- {
- // The FocusSet is not shared and deleting it is the right thing
- // to do.
- ODDeleteObject(gGlobals->fUIFocusSet);
-
- // Dispose the memory used by our ISO strings.
- ODDisposePtr(gGlobals->fSndDataKind);
- ODDisposePtr(gGlobals->fSndFileKind);
- ODDisposePtr(gGlobals->fAppleHFSFlavor);
-
- // We need to remove our menus from the menubar and dispose of
- // them to free up their memory.
- for (ODSShort index = 0; index < kNumMenus; index++)
- {
- ODSShort id = kBaseMenuID + index;
-
- MenuHandle menu = gGlobals->fMenuBar->GetMenu(ev, id);
- gGlobals->fMenuBar->RemoveMenu(ev, id);
- if ( menu != kODNULL )
- {
- CUsingLibraryResources res;
- ReleaseResource((Handle) menu);
- }
- }
-
- // Release the menubar.
- ODReleaseObject(ev, gGlobals->fMenuBar);
-
- // Dispose the controls picture.
- if ( gGlobals->fControlsPict != kODNULL )
- ODDisposeHandle(gGlobals->fControlsPict);
-
- // Dispose the thumbnail picture.
- if ( gGlobals->fThumbnail != kODNULL )
- ReleaseResource(gGlobals->fThumbnail);
-
- // Now, clean up the globals struct.
- ODDeleteObject(gGlobals);
- }
-
- // Remove and release our display frames.
- if ( fDisplayFrames )
- {
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- // Delete the proxy object and its contents. The frame's
- // refcount will be decremented in the proxy destructor.
- fiter.RemoveCurrent();
- delete proxy;
- }
-
- // Delete the display frame collection.
- ODDeleteObject(fDisplayFrames);
- }
-
- // If something goes wrong while we are cleaning up, we must
- // let the Draft now because there may be some refcounted objects
- // which did not get released. Not to mention, possible memory
- // leaks.
- }
-
- //------------------------------------------------------------------------------
- // Method: Purge
- // Origin: ODPart
- //
- // Description: This method is called when the OpenDoc requires more memory for
- // allocating objects and just before a part is deleted. The part
- // should free up as much memory as it can.
- //
- // The part determines which views are being "used" in its display
- // frames. The resources for the unused view types are then purged.
- //------------------------------------------------------------------------------
-
- ODSize SoundEditor::Purge( Environment* ev,
- ODSize size )
- {
- SOM_Trace("SoundEditor","Purge");
-
- // Purge is called during the creation of stationery. However,
- // we have not create our internal display frames list, so
- // trying to iterate over it would be futile.
- if ( fDisplayFrames == kODNULL ) return 0;
-
- ODSize bytesFreed = 0;
- ODBoolean usingThumbnail = kODFalse;
-
- // Iterate over the frames we are displayed through and determine which
- // view types are currently in use.
-
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- // If the display frame is real (has been "connected" or was "added")
- // get its view type; otherwise, ignore it.
- if ( proxy->FrameIsLoaded(ev) )
- {
- ODTypeToken frameView = proxy->GetFrame(ev)->GetViewType(ev);
-
- if ( frameView == gGlobals->fThumbnailView )
- usingThumbnail = kODTrue;
-
- // Release the frame reference, but don't get rid of the
- // proxy object because we're not done with the frame. If
- // all parts release their references the frame will be
- // purged from memory.
- proxy->Purge(ev);
- }
- }
-
- // Based on the usage of the supported view types, free up as much
- // memory as possible.
-
- if ( !usingThumbnail && gGlobals->fThumbnail != kODNULL )
- {
- bytesFreed += ODGetHandleSize(gGlobals->fThumbnail);
- ReleaseResource(gGlobals->fThumbnail);
- gGlobals->fThumbnail = kODNULL;
- }
-
- return bytesFreed;
- }
-
- //------------------------------------------------------------------------------
- // Method: InternalizeStateInfo
- // Origin: SoundEditor
- //
- // Description: This method is used to read in "state" information for the part.
- // This is information related to the workings of the part editor,
- // not the content.
- //
- // The part writes out a list of weak references to its display
- // frames. This allows the part to reuse the same display frames
- // each time the document is opened. Those references are read
- // back in and validated here.
- //
- // Note: The function StorageUnitGetValue simplifies the use of
- // ODByteArrary, which is required the StorageUnit interface. Look
- // in StorUtil.h/cpp for an example of using the ODByteArray struct.
- //------------------------------------------------------------------------------
-
- void SoundEditor::InternalizeStateInfo( Environment* ev,
- ODStorageUnit* storageUnit )
- {
- SOM_Trace("SoundEditor","InternalizeStateInfo");
-
- ODStorageUnitRef weakRef;
- ODULong size;
-
- // Internalize the part's display frame list.
-
- if ( ODSUExistsThenFocus(ev, storageUnit, kODPropDisplayFrames, kODWeakStorageUnitRefs) )
- {
- size = storageUnit->GetSize(ev);
- storageUnit->SetOffset(ev, 0);
-
- for ( ODULong offset = 0; offset < size; offset += kODStorageUnitRefSize )
- {
- TRY
- StorageUnitGetValue(storageUnit, ev, kODStorageUnitRefSize, (ODPtr) &weakRef);
-
- if ( storageUnit->IsValidStorageUnitRef(ev, weakRef) )
- {
- // We lazily internalize our display frames, meaning we don't "get"
- // the frame until we absolutely need it. This reduces the time
- // to internalize the part and the amount of memory needed.
-
- // Convert the reference into a runtime id.
- ODID frameID = storageUnit->GetIDFromStorageUnitRef(ev, weakRef);
-
- // Create a proxy class to support the lazy internalization.
- CFrameProxy* proxy = new CFrameProxy;
- proxy->InitFrameProxy(frameID, ODGetDraft(ev, storageUnit));
-
- // Add the proxy to the display frame collection.
- fDisplayFrames->Add(proxy);
- }
- CATCH_ALL
- // consume exception
- ENDTRY
- }
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: InternalizeAnnotation
- // Origin: SoundEditor
- //
- // Description: This method is used to read in content annotation for the part.
- //------------------------------------------------------------------------------
-
- void SoundEditor::InternalizeAnnotation( Environment* ev,
- ODStorageUnit* storageUnit )
- {
- SOM_Trace("SoundEditor","InternalizeAnnotation");
-
- // Internalize the default recording quality.
-
- fUnknownSound = kODTrue; // unknown sound quality for now
- fRecorder->SetQuality(siGoodQuality); // use default values
-
- if ( ODSUExistsThenFocus(ev, storageUnit, kPropRecordingQuality, kOSType) )
- {
- if ( storageUnit->GetSize(ev) > 0 )
- {
- TRY
- OSType quality;
- StorageUnitGetValue(storageUnit, ev, sizeof(OSType), &quality);
-
- // If the value we read in does not match one of the quality
- // setting we know about, then either new quality recording
- // levels have been added to the Sound Manager, or another
- // editor was bound to our content and wrote the value
- // incorrectly.
-
- if ( quality == siGoodQuality ||
- quality == siBetterQuality ||
- quality == siBestQuality)
- {
- fUnknownSound = kODFalse;
- fRecordingQuality = quality;
- fRecorder->SetQuality(quality);
- }
- CATCH_ALL
- // Consume exception. We can survive if we don't know the quality.
- ENDTRY
- }
- }
-
- // Find out the maximum number of seconds to record at current quality
- // even if original was unknown, can still give current max time
- fMaxSeconds = fRecorder->GetMaxTime(fMaxMemory, fRecordingQuality);
-
- // Internalize the recorded sound length.
-
- if ( ODSUExistsThenFocus(ev, storageUnit, kPropSecsRecorded, kODULong) )
- {
- if ( storageUnit->GetSize(ev) > 0 )
- {
- TRY
- fSecsRecorded = ODGetULongProp(ev, storageUnit, kPropSecsRecorded, kODULong);
- // Here we use a routine from StdTypIO.h, an OpenDoc Utility to simplify
- // outputting standard data types. This routine also will perform endian-
- // swapping to put the value in the right form to be standard.
- CATCH_ALL
- fSecsRecorded = -1;
- fUnknownSound = kODTrue;
- ENDTRY
- }
- }
- else // original recording length is unknown
- {
- fSecsRecorded = -1;
- fUnknownSound = kODTrue;
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: InternalizeContent
- // Origin: SoundEditor
- //
- // Description: This method is called during initialization of the part from an
- // existing document. The content of the part should be read in.
- //
- // The part has no intrinsic content, so the part does nothing.
- // The method is here for completeness.
- //------------------------------------------------------------------------------
-
- void SoundEditor::InternalizeContent( Environment* ev,
- ODStorageUnit* storageUnit )
- {
- SOM_Trace("SoundEditor","InternalizeContent");
-
- // Get a token representing the kind of data that should be internalized
- // from the given storage unit.
- ODTypeToken kindToUse = GetKindToInternalize(ev, fSession, storageUnit);
-
- // We support the old style Macintosh sound files and need to
- // check for them when we are being instantiated from an
- // existing strorage unit. We do this because the Drag&Drop code
- // will add a value for the dropped file's type and a HFSFlavor value
- // so that the file can be accessed by the target part.
- if ( (kindToUse == kODNullTypeToken || kindToUse == gGlobals->fMacSndFile)
- && ODSUExistsThenFocus(ev, storageUnit, kODPropContents, gGlobals->fAppleHFSFlavor) )
- {
- ODULong size = storageUnit->GetSize(ev);
-
- if ( size > 0 )
- {
- HFSFlavor* hfsInfo = (HFSFlavor*) ODNewPtrClear(size);
- TempODPtr autoDisposer = (ODPtr) hfsInfo;
- // This is used so that the memory block will be automatically
- // disposed when it goes out of scope or in case an exception
- // is thrown.
-
- StorageUnitGetValue(storageUnit, ev, size, hfsInfo);
-
- if (hfsInfo->fileType == kSoundFileKind)
- {
- FSSpec fileSpec = hfsInfo->fileSpec;
- ODSShort refNum = FSpOpenResFile(&fileSpec, fsRdPerm);
-
- if ( refNum != -1 && !ResError() )
- {
- TRY
- UseResFile(refNum);
-
- TRY
- // We use the utility function Read1IndResource to read
- // the resource into memory. We use this rather than just
- // calling Get1IndResource because Get1IndResource would
- // put the resoure in the application heap, and we don't
- // have much room available in the application heap. It also
- // detaches the resource from the resource fork it came from.
- ODHandle sound = Read1IndResource('snd ', 1);
-
- fPlayer->SetSound(sound);
- this->SetDirty(ev);
-
- // Remember the "preferred" kind for the data to be written as.
- if (fPreferredKind == kODNullTypeToken)
- fPreferredKind = gGlobals->fMacSndData;
-
- // Write out the preferred kind.
- SetPreferredKind(ev, storageUnit, GetKindFromToken(ev, fPreferredKind));
-
- CATCH_ALL
- fPlayer->SetSound(kODNULL);
- fSecsRecorded = 0;
- // Consume the exception.
- ENDTRY
- CATCH_ALL
- CloseResFile(refNum);
- RERAISE;
- ENDTRY
-
- CloseResFile(refNum);
- }
- }
- }
- }
- else if ( kindToUse != kODNullTypeToken )
- {
- // We support the old-style Macintosh sound scrap type "snd "
- // and need to check for it when we are being instantiated
- // from an existing strorage unit.
-
- // If we are not importing old-style data, we must be
- // reading our own data format.
-
- ODSUExistsThenFocus(ev, storageUnit, kODPropContents, GetKindFromToken(ev, kindToUse));
- // We already know it exists, but this is a convenient way to focus.
-
- ODULong soundSize = storageUnit->GetSize(ev);
- if (soundSize > 0)
- {
- ODHandle tempHandle = ODNewHandle(soundSize);
-
- // Allocate memory for the new sound data. If we are
- // successful, dispose of any old sound data and assign
- // the new storage to our part field.
- fPlayer->SetSound(tempHandle);
-
- TempHandleLockAndRememberState lock(fPlayer->GetSound());
- ODValue soundDataPtr = *lock;
- StorageUnitGetValue(storageUnit, ev, soundSize, soundDataPtr);
- }
- else
- {
- fPlayer->SetSound(kODNULL);
- fSecsRecorded = 0;
- }
- }
-
- // If we don't have a preferred kind yet, use the kind that was found,
- // if any. Otherwise, use our default kind.
- if ( fPreferredKind == kODNullTypeToken )
- fPreferredKind = (kindToUse != kODNullTypeToken) ? kindToUse
- : gGlobals->fNativeData;
- }
-
- //------------------------------------------------------------------------------
- // Method: CloneInto
- // Origin: ODPart
- //
- // Description: This method is called during cloning, typically during data
- // interchange operations (e.g. Cut/Paste). The part should
- // write out its current state and content.
- //
- // Parent: The part's parent class was called before this method was
- // dispatched to (see som_SamplePart.cpp).
- //------------------------------------------------------------------------------
-
- void SoundEditor::CloneInto( Environment* ev,
- ODDraftKey key,
- ODStorageUnit* destinationSU,
- ODFrame* initiatingFrame )
- {
- SOM_Trace("SoundEditor","CloneInto");
-
- // We must first verify that we've never written to this storage unit.
- // If we have, we should do nothing, otherwise we need to write out
- // the current state of the part content.
-
- if ( !destinationSU->Exists(ev, kODPropContents, kSoundEditorKind, 0)
- && !destinationSU->Exists(ev, kODPropContents, gGlobals->fSndDataKind, 0) )
- {
- // Add the properties we need to successfully externalize
- // ourselves into the destination storage unit.
- this->CheckAndAddProperties(ev, destinationSU);
-
- // Write out the part's state information.
- this->ExternalizeStateInfo(ev, destinationSU, key, initiatingFrame);
-
- // Write out the part's content annotation.
- this->ExternalizeAnnotation(ev, destinationSU, key, initiatingFrame);
-
- // Write out the part's content.
- this->ExternalizeContent(ev, destinationSU, key, initiatingFrame,
- fPreferredKind);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Externalize
- // Origin: ODPart
- //
- // Description: This method is called when the user saves the document. The part
- // should write out its state and content if changes have occurred
- // and if our storage is writeable.
- //
- // Parent: The part's parent class was called before this method was
- // dispatched to (see som_SamplePart.cpp).
- //------------------------------------------------------------------------------
-
- void SoundEditor::Externalize( Environment* ev )
- {
- SOM_Trace("SoundEditor","Externalize");
-
- TRY
- if ( fDirty && !fReadOnlyStorage )
- {
- // Get our storage unit.
- ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
-
- // Verify that the storage unit has the appropriate properties
- // and values to allow us to run. If not, add them.
- this->CheckAndAddProperties(ev, storageUnit);
-
- // Verify that there are no "bogus" values in the Content
- // property.
- this->CleanseContentProperty(ev, storageUnit);
-
- // Write out the part's state information.
- this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
-
- // Write out the part's content annotation.
- this->ExternalizeAnnotation(ev, storageUnit, kODNULLKey, kODNULL);
-
- // Write out the part's content.
- this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL,
- fPreferredKind);
-
- // Flag our part as no longer being dirty.
- fDirty = kODFalse;
- }
- CATCH_ALL
- // Alert the user of the problem.
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrExternalizeFailed);
- // Change the exception value, so the DocShell doesn't display an
- // error dialog.
- SetErrorCode(kODErrAlreadyNotified);
- // Alert the caller.
- RERAISE;
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: ExternalizeKinds
- // Origin: ODPart
- //
- // Description: This method is called by OpenDoc or the containing part when
- // either require the part to write out one or more of the editors
- // supported content formats.
- //
- // The part is responsible for writing out the kinds it supports
- // from the list in its fidelity order (the list will probably not
- // be in the right order).
- //------------------------------------------------------------------------------
-
- void SoundEditor::ExternalizeKinds( Environment* ev,
- ODTypeList* kindset )
- {
- SOM_Trace("SoundEditor","ExternalizeKinds");
-
- if ( !fReadOnlyStorage )
- {
- ODBoolean preferredKindWritten = kODFalse;
-
- // Get our storage unit.
- ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
-
- // Verify that the storage unit has the appropriate properties
- // and values to allow us to run. If not, add them.
- this->CheckAndAddProperties(ev, storageUnit);
-
- // Verify that there are no "bogus" values in the Content
- // property.
- this->CleanseContentProperty(ev, storageUnit);
-
- // Write out each of the kinds that we support from the list.
- // Note: We should externalize in fidelity order, but since the
- // content of SoundEditor's types is about the same, we don't
- // check the order.
- for ( TempODTypeListIterator kind(ev, kindset) ;
- kind.IsNotComplete() ; kind.Next() )
- {
- ODTypeToken kindToken = fSession->Tokenize(ev, kind);
-
- if ( IsKindSupported(ev, kindToken) )
- {
- // Write out the part's content in the prescribed format.
- this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL, kindToken);
-
- if ( kindToken == fPreferredKind )
- preferredKindWritten = kODTrue;
- }
- }
-
- // Even if the kind set contains no types we support, we must at least
- // write out our current "preferred" kind.
- if ( !preferredKindWritten )
- {
- // Write out the part's preferred content kind, which, for SamplePart,
- // is the only kind.
- this->ExternalizeContent(ev, storageUnit, kODNULLKey, kODNULL, fPreferredKind);
- }
-
- // Write out the part's content annoation.
- this->ExternalizeAnnotation(ev, storageUnit, kODNULLKey, kODNULL);
-
- // Write out the part's state information.
- this->ExternalizeStateInfo(ev, storageUnit, kODNULLKey, kODNULL);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ChangeKind
- // Origin: ODPart
- //
- // Description: This method is called in response to the user
- // selecting a different item in the Kind popup in the
- // part/documet info dialog. This signals to the part
- // that the user wishes the default format of the data
- // written out to be changed.
- //
- // The editor should record the new "preferred" kind and change the
- // UI, if necessary, to allow editing of that kind. Don't write the
- // properties/values/data until Externalize is called.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ChangeKind( Environment* ev,
- ODType kind )
- {
- SOM_Trace("SoundEditor","ChangeKind");
-
- ODTypeToken kindToken = fSession->Tokenize(ev, kind);
-
- // Make sure we support the kind we are being asked to use.
-
- // First, if the kind we were asked to use is the "file kind", then
- // use the data kind instead. The file kind is intended to only
- // refer to incoming data in a drag-and-drop (or maybe some other
- // file-based binding) and be paired with an HFS kind with the
- // file specification. However, OpenDoc 1.0 shows this in its
- // Kind popup menu, and there is no way to prevent it from appearing
- // there.
- if ( kindToken == gGlobals->fMacSndFile )
- kindToken = gGlobals->fMacSndData;
- else if ( !IsKindSupported(ev, kindToken) )
- THROW(kODErrInvalidValueType);
-
- // Get our storage unit.
- ODStorageUnit* storageUnit = fSelf->GetStorageUnit(ev);
-
- // We need to make sure the "Preferred Kind" property has the correct
- // value right away so that OpenDoc knows our preferred kind has changed.
- if ( fPreferredKind != kindToken )
- {
- fPreferredKind = kindToken;
-
- // Write out the user's preferred kind.
- SetPreferredKind(ev, storageUnit, GetKindFromToken(ev, kindToken));
-
- // Changing our kind dirties our content.
- this->SetDirty(ev);
-
- // Immediately externalize ourselves in the "new" format.
- this->Externalize(ev);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ExternalizeStateInfo
- // Origin: SoundEditor
- //
- // Description: This method is called during externalization of the part. The
- // current "state" of the part should be written out. This "state"
- // information may be lost during Data Interchange operations, so
- // the part needs to recover gracefully if information is missing
- // or incomplete.
- //
- // Note: The function StorageUnitSetValue is a macro which simplifies
- // the use of ODByteArrary, which is required the StorageUnit
- // interface. Look in StorUtil.h/cpp for an example of using the
- // ODByteArray struct.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ExternalizeStateInfo( Environment* ev,
- ODStorageUnit* storageUnit,
- ODDraftKey key,
- ODFrame* scopeFrame )
- {
- SOM_Trace("SoundEditor","ExternalizeStateInfo");
-
- ODID scopeFrameID = (scopeFrame ? scopeFrame->GetID(ev) : kODNULLID);
- ODDraft* fromDraft = ODGetDraft(ev,fSelf);
-
- // Set up the preferred kind property with our preferred kind.
-
- WASSERT(IsKindSupported(ev, fPreferredKind));
- SetPreferredKind(ev, storageUnit, GetKindFromToken(ev, fPreferredKind));
-
- // Externalize the part's display frame list.
-
- storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined,
- kODWeakStorageUnitRefs, 0, kODPosUndefined);
-
- // Persistent object references are stored in a side table, rather than
- // in the property/value stream. Thus, deleting the contents of a value
- // will not "delete" the references previously written to that value. To
- // completely "delete" all references written to the value, we must
- // remove the value and add it back.
- storageUnit->Remove(ev);
- storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
-
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- // Get the ID of the frame we are going to weakly reference.
- ODID frameID = proxy->GetID();
-
- // If a draft key exists, then we are being cloned to another draft.
- // We must "weak" clone our display frame and reference the cloned
- // frame. The part re-uses the frameID variable so there aren't two
- // different GetWeakStorageUnitRef calls.
- if ( key )
- frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
-
- // Write out weak references to each of the part's display frames.
- ODStorageUnitRef weakRef;
- storageUnit->GetWeakStorageUnitRef(ev, frameID, weakRef);
- TRY
- StorageUnitSetValue(storageUnit, ev, kODStorageUnitRefSize, (ODPtr)&weakRef);
- CATCH_ALL
- // consume the exception
- ENDTRY
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ExternalizeAnnotation
- // Origin: SoundEditor
- //
- // Description: This method is called during externalization of the part. The
- // annotation consists of values which are stored in the content
- // but need to be readily accessible.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ExternalizeAnnotation( Environment* ev,
- ODStorageUnit* storageUnit,
- ODDraftKey key,
- ODFrame* scopeFrame )
- {
- SOM_Trace("SoundEditor","ExternalizeAnnotation");
-
- // Externalize the default recording quality.
- storageUnit->Focus(ev, kPropRecordingQuality, kODPosUndefined,
- kOSType, 0, kODPosUndefined);
-
- OSType rQuality = fRecorder->GetQuality();
- StorageUnitSetValue(storageUnit, ev, sizeof(OSType), &rQuality);
-
- // Externalize the recorded sound length.
- ODSetULongProp(ev, storageUnit, kPropSecsRecorded, kODULong, fSecsRecorded);
- // Here we use a routine from StdTypIO.h, an OpenDoc Utility to simplify
- // outputting standard data types. This routine also will perform endian-
- // swapping to put the value in the right form to be standard.
- }
-
- //------------------------------------------------------------------------------
- // Method: ExternalizeContent
- // Origin: SoundEditor
- //
- // Description: This method is called during exteralization of the part. The
- // content of the part should be written out.
- //
- // The part has no intrinsic content, so the part does nothing.
- // The method is here for completeness.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ExternalizeContent( Environment* ev,
- ODStorageUnit* storageUnit,
- ODDraftKey key,
- ODFrame* scopeFrame,
- ODTypeToken kindToken )
- {
- SOM_Trace("SoundEditor","ExternalizeContent");
-
- // Focus to the preferred kind for the part.
-
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined,
- GetKindFromToken(ev, kindToken), 0, kODPosUndefined);
-
- if ( fPlayer->GetSound() )
- {
- // Write out the data.
-
- ODULong oldSize = storageUnit->GetSize(ev);
- ODULong soundSize = ODGetHandleSize(fPlayer->GetSound());
- TempHandleLockAndRememberState lock(fPlayer->GetSound());
- ODValue soundDataPtr = *lock;
-
- StorageUnitSetValue(storageUnit, ev, soundSize, soundDataPtr);
-
- if ( oldSize > soundSize )
- storageUnit->DeleteValue(ev, oldSize - soundSize);
- }
- else
- {
- ODULong oldSize = storageUnit->GetSize(ev);
- if ( oldSize > 0 )
- storageUnit->DeleteValue(ev, oldSize);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: CleanseContentProperty
- // Origin: SoundEditor
- //
- // Description: This method is called during externalization of the part so
- // that the part can remove any value in the content property
- // that it cannot "accurately" write to.
- //
- // Note: "Additional" values will be added to a part's content property
- // during Drag & Drop operations.
- //------------------------------------------------------------------------------
-
- void SoundEditor::CleanseContentProperty( Environment* ev,
- ODStorageUnit* storageUnit )
- {
- SOM_Trace("SoundEditor","CleanseContentProperty");
-
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0,
- kODPosAll);
-
- ODULong numValues = storageUnit->CountValues(ev);
-
- for (ODULong index = numValues; index >= 1; index--)
- {
- // Index from 1 to n through the values.
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL,
- index, kODPosUndefined);
- TempODValueType value = storageUnit->GetType(ev);
-
- #if 0
- // If the value type is not one we support, remove it.
- if ( !ODISOStrEqual(value, kSoundEditorKind) &&
- !ODISOStrEqual(value, gGlobals->fSndDataKind) )
- {
- storageUnit->Remove(ev);
- }
- #else
- ODBoolean remove = kODTrue;
-
- if ( (fPreferredKind == gGlobals->fNativeData || fPreferredKind == kODNullTypeToken)
- && ODISOStrEqual(value, kSoundEditorKind) )
- remove = kODFalse;
-
- if ( ODISOStrEqual(value, gGlobals->fSndDataKind) )
- remove = kODFalse;
-
- if (remove)
- storageUnit->Remove(ev);
- #endif
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: CheckAndAddProperties
- // Origin: SoundEditor
- //
- // Description: This method is called during externalization of the part to
- // verify that all the properties needed to persistently represent
- // the current running state of the part exist.
- //
- // The part adds the default content property, a preferred editor
- // property (to aid in part binding), and a display frames property.
- //
- // Note: The function StorageUnitSetValue is a macro which simplifies
- // the use of ODByteArrary, which is required the StorageUnit
- // interface. Look in StorUtil.h/cpp for an example of using the
- // ODByteArray struct.
- //------------------------------------------------------------------------------
-
- void SoundEditor::CheckAndAddProperties( Environment* ev,
- ODStorageUnit* storageUnit )
- {
- SOM_Trace("SoundEditor","CheckAndAddProperties");
-
- // Create our content property and preferred content property kind.
-
- if ( !storageUnit->Exists(ev, kODPropContents, kODNULL, 0) )
- storageUnit->AddProperty(ev, kODPropContents);
- if ( !storageUnit->Exists(ev, kODPropContents, kSoundEditorKind, 0) )
- {
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
- storageUnit->AddValue(ev, kSoundEditorKind);
- }
- if ( !storageUnit->Exists(ev, kODPropContents, gGlobals->fSndDataKind, 0) )
- {
- storageUnit->Focus(ev, kODPropContents, kODPosUndefined, kODNULL, 0, kODPosUndefined);
- storageUnit->AddValue(ev, gGlobals->fSndDataKind);
- }
-
- // Since we are setting up the preferred kind property, we just write
- // out our default "kind" for the editor. We can write out the user
- // chosen kind in the ExternalizeStateInfo method.
-
- if ( !storageUnit->Exists(ev, kODPropPreferredKind, kODISOStr, 0) )
- SetPreferredKind(ev, storageUnit, kSoundEditorKind);
-
- // Add our content annotation for recording quality.
-
- if ( !storageUnit->Exists(ev, kPropRecordingQuality, kOSType, 0) )
- storageUnit->AddProperty(ev, kPropRecordingQuality)->AddValue(ev, kOSType);
-
- // Add our content annotation for recorded sound length.
-
- if ( !storageUnit->Exists(ev, kPropSecsRecorded, kODULong, 0) )
- storageUnit->AddProperty(ev, kPropSecsRecorded)->AddValue(ev, kODULong);
-
- // Add our display frame list.
-
- if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODNULL, 0) )
- storageUnit->AddProperty(ev, kODPropDisplayFrames);
- if ( !storageUnit->Exists(ev, kODPropDisplayFrames, kODWeakStorageUnitRefs, 0) )
- {
- storageUnit->Focus(ev, kODPropDisplayFrames, kODPosUndefined, kODNULL, 0, kODPosAll);
- storageUnit->AddValue(ev, kODWeakStorageUnitRefs);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: SetDirty
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when the content or state of
- // the part has been modified by the user and the "Save" menu item
- // should be enabled.
- //------------------------------------------------------------------------------
-
- void SoundEditor::SetDirty( Environment* ev )
- {
- SOM_Trace("SoundEditor","SetDirty");
-
- // There is no need to repeatedly tell the draft we have changed;
- // once is sufficient.
- if ( !fDirty && !fReadOnlyStorage )
- {
- fDirty = kODTrue;
- ODGetDraft(ev,fSelf)->SetChangedFromPrev(ev);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ReadPartInfo
- // Origin: ODPart
- //
- // Description: When a frame is being internalized by the Draft, it will ask the
- // owner (part) to read in its info annotation on the frame.
- //
- // The part uses a C++ helper class to encapsulate the information
- // we store with each frame, so we let it internalize itself from
- // the storage unit view.
- //------------------------------------------------------------------------------
-
- ODInfoType SoundEditor::ReadPartInfo( Environment* ev,
- ODFrame* frame,
- ODStorageUnitView* storageUnitView )
- {
- SOM_Trace("SoundEditor","ReadPartInfo");
-
- CFrameInfo* frameInfo = new CFrameInfo(fSession);
-
- TRY
- frameInfo->InitFromStorage(ev, storageUnitView);
- CATCH_ALL
- // Clean up the allocated memory.
- ODDeleteObject(frameInfo);
- // Alert the caller.
- RERAISE;
- ENDTRY
-
- return (ODInfoType) frameInfo;
- }
-
- //------------------------------------------------------------------------------
- // Method: WritePartInfo
- // Origin: ODPart
- //
- // Description: When a frame is being externalized by the Draft, it will ask the
- // owner (part) to write out its info annotation on the frame.
- //
- // The part uses a C++ helper class to encapsulate the information
- // we store with each frame, so we let it externalize itself to
- // the storage unit view.
- //------------------------------------------------------------------------------
-
- void SoundEditor::WritePartInfo( Environment* ev,
- ODInfoType partInfo,
- ODStorageUnitView* storageUnitView )
- {
- SOM_Trace("SoundEditor","WritePartInfo");
-
- // Tell our frame info class to write itself out into the pre-
- // focused storage unit.
- ((CFrameInfo*) partInfo)->Externalize(ev, storageUnitView);
- }
-
- //------------------------------------------------------------------------------
- // Method: ClonePartInfo
- // Origin: ODPart
- //
- // Description: When a frame is being cloned by the Draft, it will ask the owner
- // (part) to clone its info annotation on the frame.
- //
- // The part uses a C++ helper class to encapsulate the information
- // we store with each frame, so we let it clone itself to the
- // storage unit view.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ClonePartInfo( Environment* ev,
- ODDraftKey key,
- ODInfoType partInfo,
- ODStorageUnitView* storageUnitView,
- ODFrame* scopeFrame )
- {
- SOM_Trace("SoundEditor","ClonePartInfo");
-
- // Tell our frame info class to write itself out into the pre-
- // focused storage unit.
- ((CFrameInfo*) partInfo)->CloneInto(ev, key, storageUnitView, scopeFrame);
- }
-
- //==============================================================================
- #pragma mark • Layout •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: DisplayFrameAdded
- // Origin: ODPart
- //
- // Description: This method is called in response to a frame being created for
- // the part.
- //
- // The part records the existence of a new display frame in its
- // internal display frame list, as well as, verify that the frame
- // is "set up" correctly (i.e., valid viewType). The part also
- // creates and stores its "frame info" class in the new frame.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DisplayFrameAdded( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","DisplayFrameAdded");
-
- // If we are being embedded in another part, the presentation field
- // will (most likely) be unset; we need to set it something meaningful.
- // The view field may also be unset, if so, we prefer to be displayed
- // in a frame view.
-
- if ( frame->GetPresentation(ev) != gGlobals->fControlsPresentation )
- frame->SetPresentation(ev, gGlobals->fControlsPresentation);
-
- if ( frame->GetViewType(ev) == kODNullTypeToken )
- frame->SetViewType(ev, gGlobals->fFrameView);
-
- // Hang our "state" info off of the new display frame. We use
- // the CFrameInfo object for activation, updating, and window
- // maintenance.
-
- CFrameInfo* frameInfo = new CFrameInfo(fSession);
- frame->SetPartInfo(ev, (ODInfoType) frameInfo);
-
- // If the frame being added is a root frame, we know that a window
- // is associated with this frame. Notify ourselves that we need to
- // clean it up when the frame goes away.
- if ( frame->IsRoot(ev) )
- frameInfo->SetShouldDisposeWindow(kODTrue);
-
- // The proxy class will refcount the frame passed to it, so we
- // don't need to worry about refcounting the display frame.
- CFrameProxy* proxy = new CFrameProxy;
- proxy->InitFrameProxy(ev, frame);
-
- // Add the proxy to the display frame collection.
- fDisplayFrames->Add(proxy);
-
- // Since we maintain a persistent list of weak references to our
- // display frames, having one added to the part dirties it.
- this->SetDirty(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: DisplayFrameConnected
- // Origin: ODPart
- //
- // Description: This method is called when one of our display frames, previously
- // written out, is internalized. This method is called instead of
- // DisplayFrameAdded because a "new" frame is not being created;
- // an existing one is being reconstituted.
- //
- // The part has nothing special to do, so we just add it to the
- // part's internal display frame list.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DisplayFrameConnected( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","DisplayFrameConnected");
-
- // Iterate over our display collection to match the frame with
- // an existing proxy with the correct frame ID. If we find it,
- // replace the ID with the actual frame. If we don't find it,
- // treat it as a newly "added" frame.
- ODBoolean found = kODFalse;
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- if ( proxy->GetID() == frame->GetID(ev) )
- {
- // The proxy class will refcount the frame passed to it, so we
- // don't need to worry about refcounting the display frame.
- proxy->SetFrame(ev, frame);
- found = kODTrue;
- }
- }
-
- // Parts typically operate under the assumption that they have previous
- // knowledge of a frame before it is connected to it. This knowledge
- // should come from having read in the frame reference when the part
- // was internalized. If the frame is an "unknown", the part was probably
- // bound to another editors storage unit because the editor is missing or
- // the user changed the editor in the Info dialog.
- if ( found )
- {
- // If a display frame is connected to us with an unrecognizable
- // presentation, we need to set it to something meaningful.
- if ( frame->GetPresentation(ev) != gGlobals->fControlsPresentation )
- frame->SetPresentation(ev, gGlobals->fControlsPresentation);
-
- // If the frame being added is a root frame, we know that a window
- // is associated with this frame. Notify ourselves that we need to
- // clean it up when the frame goes away.
- if ( frame->IsRoot(ev) )
- {
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- frameInfo->SetShouldDisposeWindow(kODTrue);
-
- // In addition, we need to verify that the frame is in "frame" view.
- // If the user dragged an icon from a document to Finder and then
- // opens the resultant document, the view would be "icon". However
- // displaying a icon is useless, so we need to change the view to
- // frame.
- if ( frame->GetViewType(ev) != gGlobals->fFrameView )
- frame->SetViewType(ev, gGlobals->fFrameView);
- }
- }
- else
- {
- // If an unrecognizable frame is connected to us, treat it like a "new"
- // frame and call our method to add it.
- this->DisplayFrameAdded(ev, frame);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: DisplayFrameRemoved
- // Origin: ODPart
- //
- // Description: This method is called in response to a frame being removed from
- // the part.
- //
- // The part removes the frame from its internal display frame list
- // and reliquishes any foci that it still owned. Lastly, if the
- // frame has a source frame (it was the root frame of a part
- // window), we will record the part window bounds so that any
- // subsequent part windows opened on the source frame will appear
- // in the same location.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DisplayFrameRemoved( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","DisplayFrameRemoved");
-
- TRY
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // Make sure to unregister the "idle" frame if the user
- // closes the palette window while a sound is playing; otherwise,
- // a "refcount" error will occur.
- if ( fPlayer->GetFrame() == frame )
- {
- fSession->GetDispatcher(ev)->UnregisterIdle(ev, fSelf, frame);
- fPlayer->SetFrame(kODNULL);
- }
-
- // Make sure the frame going away does not own any foci. Forgetting
- // to do this, will cause a "refcounting" error when the frame
- // is deleted by the draft.
- this->RelinquishAllFoci(ev, frame);
-
- // If removing a child window, show zoom rects back to source.
- // NOTE: This has to be done before CleanupDisplayFrame because
- // CleanupDisplayFrame will remove the relationship.
- if ( frame->IsRoot(ev) && frameInfo->HasSourceFrame() )
- {
- TempODWindow window = frame->AcquireWindow(ev);
- this->ZoomPartWindow(ev, frameInfo->GetSourceFrame(ev),
- window, kWindowClosing);
- }
-
- // Clean up the display frame.
- this->CleanupDisplayFrame(ev, frame, kFrameRemoved);
-
- // Clean up any associated window.
- this->CleanupWindow(ev, frame);
-
- // Clean up the display frame, remove it from our internal list,
- // and let go of it.
- frame->SetPartInfo(ev, (ODInfoType) kODNULL);
- ODDeleteObject(frameInfo);
-
- // Remove the display frame from our collection.
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- if ( ODObjectsAreEqual(ev, proxy->GetFrame(ev), frame) )
- {
- // Delete the proxy object and its contents. The frame's
- // refcount will be decremented in the proxy destructor.
- fiter.RemoveCurrent();
- delete proxy;
- }
- }
-
- // Since we maintain a persistent list of weak references to our
- // display frames, having one removed from the part dirties it.
- this->SetDirty(ev);
- CATCH_ALL
- // Alert the user of the problem.
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
- // Change the exception value, so the DocShell doesn't display an
- // error dialog.
- SetErrorCode(kODErrAlreadyNotified);
- // Alert the caller.
- RERAISE;
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: DisplayFrameClosed
- // Origin: ODPart
- //
- // Description: This method is called in response to a frame being closed as a
- // result of the document having been closed by the user.
- //
- // The part behaves much the same way that it would if a frame were
- // removed (see above), except that we don't need to cache runtime
- // information.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DisplayFrameClosed( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","DisplayFrameClosed");
-
- TRY
- // Make sure to unregister the "idle" frame if the user
- // closes the palette window while a sound is playing; otherwise,
- // a "refcount" error will occur.
- if ( fPlayer->GetFrame() == frame )
- {
- fSession->GetDispatcher(ev)->UnregisterIdle(ev, fSelf, frame);
- fPlayer->SetFrame(kODNULL);
- }
-
- // Make sure the frame going away does own any foci. Forgetting
- // to do this, will cause a "refcounting" error when the frame
- // is deleted by the draft.
- this->RelinquishAllFoci(ev, frame);
-
- // Clean up the display frame.
- this->CleanupDisplayFrame(ev, frame, kFrameClosed);
-
- // Clean up any associated window.
- this->CleanupWindow(ev, frame);
-
- // Clean up the display frame, remove it from our internal list,
- // and let go of it.
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- frame->SetPartInfo(ev, (ODInfoType) kODNULL);
- ODDeleteObject(frameInfo);
-
- // Remove the display frame from our collection.
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- if ( proxy->GetID() == frame->GetID(ev) )
- {
- // Release the frame reference, but don't get rid of the
- // proxy object because "closed" frames may be reconnected
- // before the document is closed.
- proxy->Purge(ev);
- }
- }
-
- CATCH_ALL
- // Alert the user of the problem.
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrRemoveFrame);
- // Change the exception value, so the DocShell doesn't display an
- // error dialog.
- SetErrorCode(kODErrAlreadyNotified);
- // Alert the caller.
- RERAISE;
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: CleanupDisplayFrame
- // Origin: SoundEditor
- //
- // Description: This method is called when a frame has been closed or removed.
- // The method cleans up the references and state information stored
- // in the CFrameInfo class.
- //------------------------------------------------------------------------------
-
- void SoundEditor::CleanupDisplayFrame( Environment* ev,
- ODFrame* frame,
- ODBoolean frameRemoved )
- {
- SOM_Trace("SamplePart","CleanupDisplayFrame");
-
- ODError error = noErr;
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- TRY
- // If we are the root of a child window, we need to notify
- // our source frame that we are going away.
- if ( frameInfo->HasSourceFrame() )
- {
- ODFrame* sourceFrame = frameInfo->GetSourceFrame(ev);
- CFrameInfo* sourceFrameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
-
- if ( frameRemoved )
- {
- // Invalidate the source frame. We do this because the
- // source frame may have a unique display when it has
- // been opened into a part window. This forces the
- // frame to redraw "not opened".
- sourceFrame->Invalidate(ev, kODNULL, kODNULL);
- }
-
- // Tell the source frame that its dependent is going away.
- sourceFrameInfo->ReleaseDependentFrame(ev);
-
- // Release our reference to the source frame.
- frameInfo->ReleaseSourceFrame(ev);
-
- // If the frame is the root, it is a part window going away
- // and we need to notify our source frame that it no longer
- // has a part window.
- if ( frame->IsRoot(ev) )
- sourceFrameInfo->SetPartWindow(ev, kODNULL);
- }
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- TRY
- // If the frame was removed from the document, we need to remove
- // any child window displaying that frame.
- if ( frameRemoved )
- {
- // If we have a child window, we need to close it.
- ODWindow* window = frameInfo->AcquirePartWindow(ev);
- if ( window )
- {
- frameInfo->SetPartWindow(ev, kODNULL);
- window->CloseAndRemove(ev);
- }
- }
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- TRY
- // If we have dependent frames, we need to notify them that we
- // are going away.
-
- if ( frameInfo->HasDependentFrame() )
- {
- // Get the frame that is dependent on this one. We can safely
- // do this because we only reference our own display frames.
- ODFrame* dependentFrame = frameInfo->GetDependentFrame(ev);
- CFrameInfo* dependentFrameInfo = (CFrameInfo*) dependentFrame->GetPartInfo(ev);
-
- // Tell the dependent frame that its source is going away.
- dependentFrameInfo->ReleaseSourceFrame(ev);
-
- // Release our reference to the dependent frame.
- frameInfo->ReleaseDependentFrame(ev);
- }
- CATCH_ALL
- error = ErrorCode();
- ENDTRY
-
- // If anything went wrong, signal an error.
- THROW_IF_ERROR(error);
- }
-
- //------------------------------------------------------------------------------
- // Method: AttachSourceFrame
- // Origin: ODPart
- //
- // Description: If the part which we are contained in is opened into a part
- // window, it is required to iterate over its embedded frames and
- // add new display frames in the part window. After each new
- // embedded frame is created, this method will be called.
- //
- // Given all that, and given our lack of interesting
- // content, we just validate the frame and attach it to its source.
- //------------------------------------------------------------------------------
-
- void SoundEditor::AttachSourceFrame( Environment* ev,
- ODFrame* frame,
- ODFrame* sourceFrame )
- {
-
- SOM_Trace("SoundEditor","AttachSourceFrame");
-
- // Tell the new frame about its source.
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- frameInfo->SetSourceFrame(ev, sourceFrame);
-
- // And tell the source about its new dependent.
- frameInfo = (CFrameInfo*) sourceFrame->GetPartInfo(ev);
- frameInfo->SetDependentFrame(ev, frame);
-
- // In both cases, refcounting of the frame and sourceFrame is
- // handled by the CFrameInfo class.
- }
-
- //------------------------------------------------------------------------------
- // Method: ViewTypeChanged
- // Origin: ODPart
- //
- // Description: This method is called in response to one of our display frame's
- // viewType field being modified. We call this method on ourselves
- // when new display frames are added, but it call also be called
- // when the user changes the view in the "part info" dialog.
- //
- // The part first loads the appropriate view icons if needed and
- // then calculates a new "used" shape based on the bounds of the
- // new view type. If any problems occur while changing the view,
- // the part defaults back to frame view (the part's default view).
- //------------------------------------------------------------------------------
-
- void
- SoundEditor::ViewTypeChanged( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","ViewTypeChanged");
-
- // Change this frame's used shape to match the new view setting.
- TempODShape newUsedShape = this->CalcNewUsedShape(ev, frame);
-
- frame->Invalidate(ev, kODNULL, kODNULL);
- frame->ChangeUsedShape(ev, newUsedShape, kODNULL);
- frame->Invalidate(ev, kODNULL, kODNULL);
- }
-
- //------------------------------------------------------------------------------
- // Method: GenerateThumbnail
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to generate a thumbnail view
- // from the current content.
- //
- // The part has no visible content, so we merely load a picture.
- //------------------------------------------------------------------------------
-
- PicHandle SoundEditor::GenerateThumbnail( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","GenerateThumbnail");
-
- if ( gGlobals->fThumbnail == kODNULL )
- {
- // In cases where a part has been instantiated from scratch and has no
- // content (yet), it is appropriate to display a PICT or some graphic
- // in place of a "real" thumbnail.
- LoadThumbnail(ev, &gGlobals->fThumbnail);
-
- // If we were unable to load the PICT resource for whatever reason
- // we will default back to a "frame" view and throw the Resource
- // Manager error as an exception.
- if ( gGlobals->fThumbnail == kODNULL )
- {
- frame->ChangeViewType(ev, gGlobals->fFrameView);
-
- // There is a bug in ResError, when resources are not found,
- // which may cause noErr to be returned. If that is the case,
- // we throw resNotFound.
- THROW_IF_ERROR(ResError());
- THROW(resNotFound);
- }
- }
-
- return (PicHandle) gGlobals->fThumbnail;
- }
-
- //------------------------------------------------------------------------------
- // Method: LoadControls
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to load its control palette.
- //------------------------------------------------------------------------------
-
- PicHandle SoundEditor::LoadControls( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","LoadControls");
-
- if ( gGlobals->fControlsPict == kODNULL )
- {
- TRY
- CUsingLibraryResources res;
-
- gGlobals->fControlsPict = (Handle) GetPicture(kControlsPICT);
-
- if ( gGlobals->fControlsPict == kODNULL )
- {
- // There is a bug in ResError, when resources are not found,
- // which may cause noErr to be returned. If that is the case,
- // we throw resNotFound.
- THROW_IF_ERROR(ResError());
- THROW(resNotFound);
- }
-
- DetachResource(gGlobals->fControlsPict);
-
- CATCH_ALL
- // If we were unable to load the PICT resource for whatever reason
- // we will default back to a "large icon" view and throw the Resource
- // Manager error as an exception.
- frame->ChangeViewType(ev, gGlobals->fLargeIconView);
- RERAISE;
- ENDTRY
- }
-
- return (PicHandle) gGlobals->fControlsPict;
- }
-
- //------------------------------------------------------------------------------
- // Method: FrameShapeChanged
- // Origin: ODPart
- //
- // Description: This method is called in response to a frame's shape being
- // altered, either by the user or the part we are embedded in.
- //
- // To keep all dependent frames in sync, we need to propogate the
- // new frame shape the frames dependent on the changed frame. This
- // is done by observing the display frames stored in the frame info
- // and calling RequestFrameShape for each.
- //------------------------------------------------------------------------------
-
- void SoundEditor::FrameShapeChanged( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","FrameShapeChanged");
-
- // Adjust the "used" shape for the new frame shape.
- TempODShape usedShape = this->CalcNewUsedShape(ev, frame);
- frame->ChangeUsedShape(ev, usedShape, kODNULL);
- }
-
- //------------------------------------------------------------------------------
- // Method: Open
- // Origin: ODPart
- //
- // Description: This method is called when OpenDoc, a containing part, or the
- // active editor would like to open a frame into a seperate window.
- // If a source frame is passed into this method, the editor is
- // being asked one of two things. If the frame is the root, we are
- // being asked to open an existing document. If the frame is not
- // the root, we are being asked to open a part window. If a source
- // frame is not specified, the editor is being asked to open a new
- // window.
- //------------------------------------------------------------------------------
-
- ODID SoundEditor::Open( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","Open");
-
- ODID windowID;
- TempODWindow window = kODNULL;
- WindowProperties* windowProperties = kODNULL;
-
- ODVolatile(window);
- ODVolatile(windowProperties);
-
- TRY
- ODBoolean adjustWindow = kODFalse;
-
- // Because the frame parameter being passed to us can be one of
- // three things, we must determine what it is; either the root
- // frame of a existing document, the source frame for a part
- // window, or null if we are opening a new document.
-
- if ( frame == kODNULL )
- {
- // Calculate the bounding rectangle for a new window
- Rect windowRect = this->CalcPartWindowSize(ev, kODNULL);
- // Get the default setting for a document window.
- windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
- // Create a Mac Window and register it with OpenDoc.
- window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
- }
- else if ( frame->IsRoot(ev) )
- {
- windowProperties = GetSavedWindowProperties(ev, frame);
-
- if ( windowProperties == kODNULL )
- {
- // Calculate the bounding rectangle for a new window
- Rect windowRect = this->CalcPartWindowSize(ev, kODNULL);
- // Get the default setting for a document window.
- windowProperties = this->GetDefaultWindowProperties(ev, kODNULL, &windowRect);
- }
-
- adjustWindow = kODTrue;
-
- // Create a Mac Window and register it with OpenDoc.
- window = this->CreateWindow(ev, frame, kODFrameObject, windowProperties);
-
- // We release the source frame here because we didn't call
- // EndGetWindowProperties and becuase we are done with it.
- ODReleaseObject(ev, windowProperties->sourceFrame);
- }
- else // frame is a source frame
- {
- window = this->AcquireFramesWindow(ev, frame);
-
- if ( window == kODNULL )
- {
- // Calculate the bounding rectangle for a new window
- Rect windowRect = this->CalcPartWindowSize(ev, frame);
- // Get the default setting for a document window.
- windowProperties = this->GetDefaultWindowProperties(ev, frame, &windowRect);
- // Create a Mac Window and register it with OpenDoc.
- window = this->CreateWindow(ev, kODNULL, kODFrameObject, windowProperties);
-
- // Tell the source frame that it is opened in a part window.
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- frameInfo->SetPartWindow(ev, window);
-
- this->ZoomPartWindow(ev, frame, window, kWindowOpening);
- }
- }
-
- // Create the window's root facet.
- window->Open(ev);
-
- // Adjust the root frame to match the window in case it was sized
- // differently when the document was created (i.e. it was dragged
- // from a container where it was sized differently).
- if ( adjustWindow )
- {
- WASSERT(frame != kODNULL);
-
- TempODShape frameShape = frame->AcquireFrameShape(ev, kODNULL);
- ODRect bbox;
- frameShape->GetBoundingBox(ev, &bbox);
- Rect bounds;
- FixedToIntRect(bbox, bounds);
-
- if ( bounds.right - bounds.left != kControlsWidth ||
- bounds.bottom - bounds.top != kControlsHeight )
- {
- window->AdjustWindowShape(ev);
- // ••• This causes the document to be dirtied!!! Do I need a better way
- // to do this? We basically need a way to resize the frame if it's
- // shape is not correct.
- }
- }
-
- // Make the window visible.
- window->Show(ev);
- // Activate and select the window.
- window->Select(ev);
-
- // Cleanup allocate memory.
- ODDeleteObject(windowProperties);
-
- // Get window id to return.
- windowID = (window ? window->GetID(ev) : kODNULLID);
-
- CATCH_ALL
- // If we threw early, the source frame's refcount may be too high.
- if ( windowProperties )
- ODSafeReleaseObject(windowProperties->sourceFrame);
- // Cleanup the created items.
- ODDeleteObject(windowProperties);
- windowID = kODNULLID;
- // Alert the caller.
- RERAISE;
- ENDTRY
-
- return windowID;
- }
-
- //------------------------------------------------------------------------------
- // Method: AcquireFramesWindow
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a frame, that has been
- // previously opened, is being opened again.
- //
- // The method retrieves the existing window for the frame and
- // returns it.
- //------------------------------------------------------------------------------
-
- ODWindow* SoundEditor::AcquireFramesWindow( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","AcquireFramesWindow");
-
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- ODWindow* window = frameInfo->AcquirePartWindow(ev);
-
- return window;
- }
-
- //------------------------------------------------------------------------------
- // Method: CreateWindow
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a window needs to be
- // created for a frame being opened.
- //
- // The part uses the information passed in windowProperties to
- // create the appropriate window. The generated window is
- // registered with OpenDoc as a new window (RegisterWindow) or as a
- // window from an existing document (RegisterWindowForFrame).
- //------------------------------------------------------------------------------
-
- ODWindow* SoundEditor::CreateWindow( Environment* ev,
- ODFrame* frame,
- ODType frameType,
- WindowProperties* windowProperties)
- {
- SOM_Trace("SoundEditor","CreateWindow");
-
- ODPlatformWindow platformWindow = kODNULL;
- ODWindow* window = kODNULL;
-
- // Using the name and the calculated rectangle, create a new window.
- // Note that we are allocating the window record in temp mem using
- // the OpenDoc memory mgr. This helps reduce app heap usage.
- // In addition, OpenDoc requires that all new windows be initially hidden
- // so that it can correctly layer windows/palettes.
- platformWindow = NewCWindow((Ptr) ODNewPtr(sizeof(WindowRecord)),
- &(windowProperties->boundsRect),
- windowProperties->title,
- kODFalse, /* visible */
- windowProperties->procID,
- (WindowPtr) -1L,
- windowProperties->hasCloseBox,
- windowProperties->refCon);
-
- if ( platformWindow )
- {
- TRY
- ODWindowState* windowState = fSession->GetWindowState(ev);
-
- ODBoolean saveWindow = ODISOStrEqual(frameType, kODFrameObject);
-
- // Tell the window object that we will be disposing the window record
- // when the root frame is closed/removed.
- ODBoolean shouldDispose = kODFalse;
-
- // Determine whether we are creating a new window (frame is null),
- // or opening a previous saved window (frame is valid).
-
- if ( frame == kODNULL )
- {
- // Tell OpenDoc about it by creating an OpenDoc window object.
- window = windowState->
- RegisterWindow(ev,
- platformWindow, // Macintosh WindowPtr
- frameType, // Frame type (Persistent/Non-persistent)
- windowProperties->isRootWindow, // Is this a document window?
- windowProperties->isResizable, // Is this window resizeable?
- windowProperties->isFloating, // Is this window floating?
- saveWindow, // Should this window be persistent?
- shouldDispose, // (see comment above)
- fSelf, // Part reference to us
- gGlobals->fFrameView, // What view should the window have?
- gGlobals->fControlsPresentation,// What presentation should the window have?
- windowProperties->sourceFrame); // The display frame being opened, if any
- }
- else
- {
- // Tell OpenDoc about it by creating an OpenDoc window object.
- window = windowState->
- RegisterWindowForFrame(ev,
- platformWindow, // Macintosh WindowPtr
- frame, // Frame type (Persistent/Non-persistent)
- windowProperties->isRootWindow, // Is this a document window?
- windowProperties->isResizable, // Is this window resizeable?
- windowProperties->isFloating, // Is this window floating?
- saveWindow, // Should this window be persistent?
- shouldDispose, // (see comment above)
- windowProperties->sourceFrame); // The display frame being opened, if any
- }
-
- CATCH_ALL
- // Cleanup Macintosh Window.
- CloseWindow(platformWindow);
- ODDisposePtr(platformWindow);
- // Get the right error message for the problem.
- ODSShort errMsgNum = (!frame && windowProperties->sourceFrame)
- ? kErrCantOpenPartWindow : kErrCantOpenDocWindow;
-
- // Alert the user of the problem.
- this->DoDialogBox(ev, frame, kErrorBoxID, errMsgNum);
- // Change the exception value, so the DocShell doesn't display an
- // error dialog.
- SetErrorCode(kODErrAlreadyNotified);
- // Alert the caller.
- RERAISE;
- ENDTRY
- }
-
- return window;
- }
-
- //------------------------------------------------------------------------------
- // Method: CleanupWindow
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a window needs to be
- // cleaned up for a frame being closed/removed.
- //
- // The part deallocates the window buffer allocated in the
- // CreateWindow() method.
- //------------------------------------------------------------------------------
-
- void SoundEditor::CleanupWindow( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SamplePart","CleanupWindow");
-
- TRY
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- if ( frameInfo->ShouldDisposeWindow() )
- {
- TempODWindow window = frame->AcquireWindow(ev);
- THROW_IF_NULL(window);
-
- ODPlatformWindow windowPtr = window->GetPlatformWindow(ev);
- CloseWindow(windowPtr);
- ODDisposePtr(windowPtr);
- }
- CATCH_ALL
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrWindowGone);
- // consume excpetion because it's not fatal.
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: GetDefaultWindowProperties
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a new window is being
- // created. The method examines the frame which is being opened
- // generates the default window parameters to pass to the
- // Mac Toolbox.
- //------------------------------------------------------------------------------
-
- WindowProperties*
- SoundEditor::GetDefaultWindowProperties( Environment* ev,
- ODFrame* sourceFrame,
- Rect* windowRect )
- {
- SOM_Trace("SoundEditor","GetDefaultWindowProperties");
-
- WindowProperties* windowProperties = new WindowProperties;
-
- TRY
- // Calculate the offset for the window based on the sourceFrame.
- if ( sourceFrame )
- this->CalcPartWindowPosition(ev, sourceFrame, windowRect);
- else
- OffsetRect(windowRect, kALittleNudge,
- GetMBarHeight() + kMacWindowTitleBarHeight);
-
- windowProperties->boundsRect = *windowRect;
-
- // Get the part's name to use for the new window.
- TempODIText windowName = GetPartName(ev, fSelf, kODCategorySampledSound);
- // Convert the ODIText into a Pascal string.
- GetITextString(windowName, windowProperties->title);
-
- // Fill in the other fields of the Window Properties struct.
- windowProperties->procID = noGrowDocProc;
- windowProperties->hasCloseBox = kODTrue;
- windowProperties->refCon = (long) kODNULL;
- windowProperties->wasVisible = kODFalse;
- windowProperties->isResizable = kODFalse;
- windowProperties->isFloating = kODFalse;
- windowProperties->isRootWindow = sourceFrame ? kODFalse : kODTrue;
- windowProperties->shouldShowLinks = kODFalse;
- windowProperties->sourceFrame = sourceFrame;
- CATCH_ALL
- // Clean up and...
- ODDeleteObject(windowProperties);
- // Alert the caller.
- RERAISE;
- ENDTRY
-
- return windowProperties;
- }
-
- //------------------------------------------------------------------------------
- // Method: GetSavedWindowProperties
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to read in saved information
- // for a window from an existing document.
- //------------------------------------------------------------------------------
-
- WindowProperties*
- SoundEditor::GetSavedWindowProperties( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","GetSavedWindowProperties");
-
- WindowProperties* windowProperties = new WindowProperties;
-
- // If we fail to load the window properties from storage, delete
- // the structure so the calling code will behave appropriately.
- if ( BeginGetWindowProperties(ev, frame, windowProperties) )
- {
- TRY
- // Note: We don't call EndGetWindowProperties because it releases the source
- // frame, which we will need after this method returns.
-
- // Get the part's name to use for the new window.
- TempODIText windowName = GetPartName(ev, fSelf, kODCategorySampledSound);
- // Convert the ODIText into a Pascal string.
- GetITextString(windowName, windowProperties->title);
-
- // Verify the window is still visible on a monitor.
-
- RgnHandle windowRgn = ODNewRgn();
- ODBoolean repositionWindow = kODFalse;
-
- // We are only concerned with the window's title bar being
- // visible, so calcuate the titlebar rect from the current
- // window bounds.
- Rect adjustedBounds = windowProperties->boundsRect;
- adjustedBounds.bottom = adjustedBounds.top;
- adjustedBounds.top -= kMacWindowTitleBarHeight;
-
- // Intersect the monitor's region
- RectRgn(windowRgn, &adjustedBounds);
- SectRgn(windowRgn, GetGrayRgn(), windowRgn);
-
- if ( !EmptyRgn(windowRgn) )
- {
- // If the visible portion of the window is too small, we need
- // to reposition it.
- Rect intersectedBounds = (**windowRgn).rgnBBox;
- if ( (intersectedBounds.right - intersectedBounds.left < kMinHorzVisPortion) ||
- (intersectedBounds.bottom - intersectedBounds.top < kMinVertVisPortion) )
- repositionWindow = kODTrue;
- }
- else
- {
- // If the window is completely offscreen, we need to reposition it.
- repositionWindow = kODTrue;
- }
- ODDisposeHandle((ODHandle) windowRgn);
-
- // If not, we need to move it so the user can see it.
- if ( repositionWindow )
- {
- Rect windowRect = (windowProperties->boundsRect);
- // Move the window to {0,0} coordinates.
- OffsetRect(&windowRect, -windowRect.left, -windowRect.top);
- // Now move the window to the default window position.
- OffsetRect(&windowRect, kALittleNudge, GetMBarHeight() + kMacWindowTitleBarHeight);
- // Save the new window position in our windowProperties.
- windowProperties->boundsRect = windowRect;
- }
- CATCH_ALL
- // Clean up and...
- ODDeleteObject(windowProperties);
- // Consume the exception.
- // Caller should try to use the default window properties.
- ENDTRY
- }
- else
- {
- // If we were unable to re-load window properties, dispose of the
- // struct.
- ODDeleteObject(windowProperties);
- }
-
- return windowProperties;
- }
-
- //------------------------------------------------------------------------------
- // Method: CalcPartWindowSize
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to determine what size a new
- // window shoud be.
- //------------------------------------------------------------------------------
-
- Rect SoundEditor::CalcPartWindowSize( Environment* ev,
- ODFrame* sourceFrame )
- {
- SOM_Trace("SoundEditor","CalcPartWindowSize");
-
- Rect windowRect;
-
- // Our frame view has a static size.
- SetRect(&windowRect, 0, 0, kControlsWidth, kControlsHeight);
-
- return windowRect;
- }
-
- //------------------------------------------------------------------------------
- // Method: CalcPartWindowPosition
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to determine where to align
- // the new window (top left corner of the screen or tiled to a
- // frame).
- //------------------------------------------------------------------------------
-
- Rect SoundEditor::CalcPartWindowPosition( Environment* ev,
- ODFrame* frame,
- Rect* partWindowBounds )
- {
- SOM_Trace("SoundEditor","CalcPartWindowPosition");
-
- ODFacet* activeFacet;
- ODRect bbox;
- Rect bounds;
-
- // We need to know which facet of the frame we are opening to position
- // the part window.
- activeFacet = this->GetActiveFacetForFrame(ev, frame);
-
- // This should never occur, but if it did, it would be fatal.
- // So we will just pass back the same rectangle.
- if ( activeFacet == kODNULL )
- return *partWindowBounds;
-
- // For the purposes of tiling, we need the to know the area of the
- // document the frame occupies. We do this by getting the bouding
- // box and offsetting it by the aggregate external window transform
- // of the facet.
-
- TempODShape frameShape = activeFacet->GetFrame(ev)->AcquireFrameShape(ev, kODNULL);
- TempODTransform windowFrameTransform = activeFacet->AcquireWindowFrameTransform(ev, kODNULL);
- TempODShape boundsShape = frameShape->Copy(ev);
-
- // Translate the bounds rect into window coordinates.
- boundsShape->Transform(ev, windowFrameTransform);
-
- // Get and convert the bounding box into a QuickDraw rectangle.
- boundsShape->GetBoundingBox(ev, &bbox);
- FixedToIntRect(bbox, bounds);
-
- // We then call our method to tile the part window.
- *partWindowBounds = TilePartWindow(ev, &bounds, partWindowBounds);
-
- // Set the port and origin so we can convert the rect to
- // global Window Mgr coordinates.
- SetPort(activeFacet->GetCanvas(ev)->GetQDPort(ev));
- SetOrigin(0,-kMacWindowTitleBarHeight);
-
- // Convert the local coordinates to global Window Mgr coordinates.
- LocalToGlobal((Point*) &partWindowBounds->top);
- LocalToGlobal((Point*) &partWindowBounds->bottom);
-
- return *partWindowBounds;
- }
-
- //------------------------------------------------------------------------------
- // Method: ZoomPartWindow
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a frame is being opened
- // or closed in the case that zooming rectangles should be shown.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ZoomPartWindow( Environment* ev,
- ODFrame* frame,
- ODWindow* window,
- ODBoolean openingWindow )
- {
- SOM_Trace("SamplePart","ZoomPartWindow");
-
- const ODSShort kNumZoomSteps = 12;
-
- Rect frameRect;
- {
- // We need to know which facet of the frame we are opening to position
- // the child window.
- ODFacet* zoomFacet = kODNULL;
-
- TRY
- zoomFacet = this->GetActiveFacetForFrame(ev, frame);
- CATCH_ALL
- ENDTRY
-
- // In case there isn't an active facet for the frame, .
- if ( zoomFacet == kODNULL )
- {
- TempODFrameFacetIterator iter(ev, frame);
- zoomFacet = iter.First();
- }
-
- if ( zoomFacet != kODNULL )
- {
- // For doing the zoom rects, we need the to know the area of the
- // document the frame occupies. We do this by getting the bouding
- // box and offsetting it by the aggregate external window transform
- // of the facet.
- TempODTransform windowFrameTransform =
- zoomFacet->AcquireWindowFrameTransform(ev, kODNULL);
- TempODShape boundsShape =
- ODCopyAndRelease(ev, zoomFacet->GetFrame(ev)
- ->AcquireFrameShape(ev, kODNULL));
-
- // Translate the bounds rect into window coordinates.
- boundsShape->Transform(ev, windowFrameTransform);
-
- // Get and convert the bounding box into a QuickDraw rectangle.
- ODRect bbox;
- boundsShape->GetBoundingBox(ev, &bbox);
- FixedToIntRect(bbox, frameRect);
-
- // Set the port and origin so we can convert the rect to
- // global Window Mgr coordinates.
- SetPort(zoomFacet->GetCanvas(ev)->GetQDPort(ev));
- SetOrigin(0, 0);
-
- // Convert the local coordinates to global Window Mgr coordinates.
- LocalToGlobal((Point*) &frameRect.top);
- LocalToGlobal((Point*) &frameRect.bottom);
- }
- }
-
- Rect windowRect;
- {
- ODPlatformWindow platformWindow = window->GetPlatformWindow(ev);
-
- windowRect = platformWindow->portRect;
- windowRect.top -= kMacWindowTitleBarHeight;
-
- // Set the port and origin so we can convert the rect to
- // global Window Mgr coordinates.
- SetPort(platformWindow);
- SetOrigin(0, 0);
-
- // Convert the local coordinates to global Window Mgr coordinates.
- LocalToGlobal((Point*) &windowRect.top);
- LocalToGlobal((Point*) &windowRect.bottom);
- }
-
- Rect fromRect = openingWindow ? frameRect : windowRect;
- Rect toRect = openingWindow ? windowRect : frameRect;
-
- if ( !openingWindow )
- window->Hide(ev);
-
- ZoomRects(&fromRect, &toRect, kNumZoomSteps,
- openingWindow ? zoomAccelerate : zoomDecelerate);
- }
-
- //------------------------------------------------------------------------------
- // Method: GetActiveFacetForFrame
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when it needs to know what the
- // current active facet is.
- //
- // The part uses this method specifically to find the facet of a
- // source frame when opening a part window.
- //------------------------------------------------------------------------------
-
- ODFacet* SoundEditor::GetActiveFacetForFrame( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","GetActiveFacetForFrame");
-
- ODFacet* facet = kODNULL;
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // If the frame is active, and it should be, get the active facet
- // from the frame state info.
- if ( frameInfo->IsFrameActive() )
- {
- facet = frameInfo->GetActiveFacet();
- }
- else
- // Otherwise, iterate over the display frames looking for one
- // that has an active facet... there should be at least one.
- {
- for ( TempODFrameFacetIterator selectedFacet(ev, frame);
- selectedFacet.IsNotComplete(); selectedFacet.Next() )
- {
- if ( selectedFacet->IsSelected(ev) )
- {
- facet = selectedFacet;
- break;
- }
- }
- }
-
- // If there are no active facets anywhere, this method should never
- // have been called, so signal an error.
- if ( facet == kODNULL )
- THROW(kODErrInvalidFrame);
-
- return facet;
- }
-
- //------------------------------------------------------------------------------
- // Method: CalcNewUsedShape
- // Origin: SoundEditor
- //
- // Description: This method is called in response to one of display frame's view
- // being changed. The method calculates the appropriate usedShape
- // for the new view type.
- //------------------------------------------------------------------------------
-
- ODShape* SoundEditor::CalcNewUsedShape( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","CalcNewUsedShape");
-
- ODShape* usedShape = kODNULL; ODVolatile(usedShape);
- RgnHandle usedRgn; ODVolatile(usedRgn);
-
- // If the view is "frame", we intentionally return a nil shape;
- // doing so, will reset the used shape to equal the frame shape.
-
- ODTypeToken view = frame->GetViewType(ev);
-
- if ( view == gGlobals->fLargeIconView ||
- view == gGlobals->fSmallIconView ||
- view == gGlobals->fThumbnailView )
- {
- TRY
- Rect bounds;
- usedRgn = ODNewRgn();
-
- if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
- {
- CUsingLibraryResources res;
-
- SetRect(&bounds, 0, 0,
- (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
- (view == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
-
- THROW_IF_ERROR(IconIDToRgn(usedRgn, &bounds, atAbsoluteCenter, kBaseResourceID));
- }
- else if ( view == gGlobals->fThumbnailView )
- {
- PicHandle thumbnail = this->GenerateThumbnail(ev, frame);
-
- bounds = (**thumbnail).picFrame;
- RectRgn(usedRgn, &bounds);
- }
-
- usedShape = frame->CreateShape(ev);
- usedShape->SetQDRegion(ev, usedRgn);
-
- CATCH_ALL
- ODSafeReleaseObject(usedShape);
- ODDisposeHandle((ODHandle)usedRgn);
- usedShape = kODNULL;
- ENDTRY
- }
-
- return usedShape;
- }
-
- //------------------------------------------------------------------------------
- // Method: UpdateFrame
- // Origin: SoundEditor
- //
- // Description: This method is called in response to one of our
- //------------------------------------------------------------------------------
-
- void
- SoundEditor::UpdateFrame( Environment* ev,
- ODFrame* frame,
- ODTypeToken view,
- ODShape* usedShape )
- {
- SOM_Trace("SoundEditor","UpdateFrame");
-
- TRY
- // Update the frame to have the new view and UsedShape.
- frame->Invalidate(ev, kODNULL, kODNULL);
- frame->SetViewType(ev, view);
- frame->ChangeUsedShape(ev, usedShape, kODNULL);
- frame->Invalidate(ev, kODNULL, kODNULL);
- CATCH_ALL
- // Failing isn't great, but we can live with it, so don't set ev.
- ENDTRY
- }
-
- //==============================================================================
- #pragma mark • Imaging •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: FacetAdded
- // Origin: ODPart
- //
- // Description: This method is called when any part adds a facet to
- // one of our display frames.
- //
- // The part calls ViewTypeChanged to load the appropriate
- // resource for display in this facet and then activates
- // the frame if we are the root part of an active window.
- //------------------------------------------------------------------------------
-
- void SoundEditor::FacetAdded( Environment* ev,
- ODFacet* facet )
- {
- SOM_Trace("SoundEditor","FacetAdded");
-
- ODFrame* frame = facet->GetFrame(ev);
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // If a root facet is being added, the frame should be activated when the
- // window is "selected". This prevents OpenDoc from getting into an
- // ambiguous state of no part having the selection focus.
-
- if ( frame->IsRoot(ev) )
- {
- frameInfo->SetActiveFacet(facet);
- frameInfo->SetFrameReactivate(kODTrue);
- }
-
- // If a frame had all of its facets removed, the frame would have
- // hidden any of its part windows. If the frame becomes visible again,
- // by having a facet added to it, we will "show" the part window for
- // the frame.
-
- if ( CountFacets(ev, frame) == 1 )
- {
- TempODWindow window = frameInfo->AcquirePartWindow(ev);
- if ( window )
- window->Show(ev);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: FacetRemoved
- // Origin: ODPart
- //
- // Description: This method is called when any part removes a facet
- // from one of our display frames.
- //
- // The part just removes the "active" note from the
- // appropriate display frame if necessary since this
- // facet will not be available, nor active, again.
- //------------------------------------------------------------------------------
-
- void SoundEditor::FacetRemoved( Environment* ev,
- ODFacet* facet )
- {
- SOM_Trace("SoundEditor","FacetRemoved");
-
- ODFrame* frame = facet->GetFrame(ev);
- TempODFrame containingFrame = frame->AcquireContainingFrame(ev);
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // If the facet was the active facet, it can no longer be.
- if ( ODObjectsAreEqual(ev, frameInfo->GetActiveFacet(), facet) )
- frameInfo->SetActiveFacet(kODNULL);
-
- // If a frame has all of its facets removed, the frame becomes
- // "hidden". If the frame owns a part window, the part window should
- // also be hidden.
-
- if ( CountFacets(ev, frame) == 0 && containingFrame == kODNULL )
- {
- TempODWindow window = frameInfo->AcquirePartWindow(ev);
- if ( window )
- window->Hide(ev);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Draw
- // Origin: ODPart
- //
- // Description: This method is called when a facet of a part's display
- // frame intersects the invalidated portion of an OpenDoc
- // window. The invalidShape parameter passed in is the
- // portion of the facet which has been invalidated.
- //
- // The part sets up the drawing environment using a
- // C++ helper class (CFocusDrawingEnv) and then calls the
- // appropriate drawing method based on the frame's
- // viewType.
- //------------------------------------------------------------------------------
-
- void SoundEditor::Draw( Environment* ev,
- ODFacet* facet,
- ODShape* invalidShape )
- {
- SOM_Trace("SoundEditor","Draw");
-
- // Focus the port and origin for drawing in our facet.
- // Note that this instance of the CFocus class
- // is being allocated on the stack. When the execution
- // leaves the scope of this method, the destructor (which
- // cleans up the drawing environment) is automatically
- // called.
- CFocus initiateDrawing(ev, facet);
-
- ODTypeToken view = facet->GetFrame(ev)->GetViewType(ev);
-
- if ( view == gGlobals->fLargeIconView || view == gGlobals->fSmallIconView )
- this->DrawIconView(ev, facet);
- else if ( view == gGlobals->fThumbnailView )
- this->DrawThumbnailView(ev, facet);
- else
- this->DrawFrameView(ev, facet);
- }
-
- //------------------------------------------------------------------------------
- // Method: DrawFrameView
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when the frame being
- // drawn is in "frame" view.
- //
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawFrameView( Environment* ev,
- ODFacet* facet )
- {
- SOM_Trace("SoundEditor","DrawFrameView");
-
- ODFrame* frame = facet->GetFrame(ev);
-
- GrafPtr thePort;
- GetPort(&thePort);
- EraseRect(&thePort->portRect);
-
- if ( frame->GetPresentation(ev) == gGlobals->fControlsPresentation )
- {
- Rect controlsRect;
- PicHandle controlsPict = this->LoadControls(ev, frame);
- SetRect(&controlsRect, 0, 0, kControlsWidth, kControlsHeight);
- DrawPicture(controlsPict, &controlsRect);
-
- // Draw the buttons.
-
- // Play button.
- if ( this->SoundPlaying() )
- this->DrawButton(ev, kPlayButton, kButtonStateOn);
- else
- this->DrawButton(ev, kPlayButton, this->IsPlayAvailable()
- ? kButtonStateNormal : kButtonStateDim);
-
- // Pause button.
- if ( this->SoundPaused() )
- this->DrawButton(ev, kPauseButton, kButtonStateOn);
- else
- this->DrawButton(ev, kPauseButton, this->IsPauseAvailable()
- ? kButtonStateNormal : kButtonStateDim);
-
- // Stop button.
- this->DrawButton(ev, kStopButton, this->IsStopAvailable()
- ? kButtonStateNormal : kButtonStateDim);
-
- // Record button.
- if ( this->SoundRecording() )
- this->DrawButton(ev, kRecordButton, kButtonStateOn);
- else
- this->DrawButton(ev, kRecordButton, this->IsRecordAvailable()
- ? kButtonStateNormal : kButtonStateDim);
-
- // Draw the empty speaker icon to start with.
- DrawEditorPicture(kSpeaker0PICT, gGlobals->fSpeakerIconRect);
-
- if ( this->SoundPlaying() && !fPlayer->IsPaused() )
- DrawEditorPicture(kSpeaker0PICT + fPlayer->GetLevel(), gGlobals->fSpeakerIconRect);
-
- if ( this->SoundRecording() )
- DrawEditorPicture(kSpeaker0PICT + fRecorder->GetLevel(), gGlobals->fSpeakerIconRect);
-
- // Draw the progress bar
-
- // First find out the current seconds value
- // If playing, then number of seconds played
- // If recording, then number of seconds recorded
- // If valid sound already recorded, then its length
- // otherwise, just zero
- if ( this->SoundPlaying() )
- fCurrentTime = fPlayer->GetTime();
- else if ( this->SoundRecording() )
- fCurrentTime = fRecorder->GetTime();
- else if ( fSecsRecorded > 0 )
- fCurrentTime = fSecsRecorded;
- else
- fCurrentTime = 0;
-
- // Draw a background of off-record color to indicate old sound if not recording
- if ( !this->SoundRecording() )
- {
- ODSShort progBar, colorBar;
-
- if ( fMaxSeconds )
- progBar = (fSecsRecorded * 100) / fMaxSeconds;
- else
- progBar = 0;
-
- if ( fUnknownSound )
- {
- progBar = 100;
- colorBar = kInvalidPAT;
- }
- else
- {
- colorBar = kRecordOffPAT;
- }
- this->DrawProgressBar(ev, facet, progBar, colorBar);
- }
-
- // If we are recording or playing, need to draw the foreground bar
- if ( this->SoundRecording() || this->SoundPlaying() )
- {
- ODSShort progBar, colorBar;
-
- colorBar = this->SoundRecording() ? kRecordOnPAT : kPlayingPAT;
-
- if ( fMaxSeconds )
- progBar = (fCurrentTime * 100) / fMaxSeconds;
- else
- progBar = 0;
-
- if ( !fUnknownSound )
- this->DrawProgressBar(ev, facet, progBar, colorBar);
- }
-
- // Draw the current and maximum recording times
- this->DrawCurrentTime(ev, facet, -1, fCurrentTime);
- DrawTime(ev, facet, gGlobals->fMaxTimeRect, 10, fMaxSeconds);
-
- if ( !frame->IsRoot(ev) )
- FrameRect(&controlsRect);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: DrawIconView
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when the frame being
- // drawn is in "standard icon" view.
- //
- // The part uses the Icon Utilities toolbox manager to
- // aid in drawing icons in active windows. The Guidelines
- // require a different appearance for selected icons in
- // inactive windows, which we do manually.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawIconView( Environment* ev,
- ODFacet* facet )
- {
- SOM_Trace("SoundEditor","DrawIconView");
-
- IconTransformType transformType = ttNone;
-
- ODFrame* frame = facet->GetFrame(ev);
- ODTypeToken viewType = frame->GetViewType(ev);
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // Check to see if the facet is selected
- if ( facet->GetHighlight(ev) == kODFullHighlight )
- transformType = ttSelected;
-
- // Check to see if the frame has been opened into a part window.
- TempODWindow window = frameInfo->AcquirePartWindow(ev);
- if ( window && window->IsShown(ev) )
- transformType |= ttOpen;
-
- // Draw the icon.
- Rect iconRect;
- SetRect(&iconRect, 0, 0,
- (viewType == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize,
- (viewType == gGlobals->fLargeIconView) ? kODLargeIconSize : kODSmallIconSize);
-
- CUsingLibraryResources res;
- PlotIconID(&iconRect, atAbsoluteCenter, transformType, kBaseResourceID);
- }
-
- //------------------------------------------------------------------------------
- // Method: DrawThumbnailView
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when the frame being
- // drawn is in "thumbnail" view.
- //
- // The part uses a picture for its thumbnail view because
- // it has no intrinsic content. A picture resource is
- // probably not sufficient for parts with real content.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawThumbnailView( Environment* ev,
- ODFacet* facet )
- {
- SOM_Trace("SoundEditor","DrawThumbnailView");
-
- // Create or retrieve a cached thumbnail picture.
- PicHandle thumbnail = this->GenerateThumbnail(ev, facet->GetFrame(ev));
-
- Rect bounds = (**thumbnail).picFrame;
- DrawPicture(thumbnail, &bounds);
- }
-
- //------------------------------------------------------------------------------
- // Method: GeometryChanged
- // Origin: ODPart
- //
- // Description: This method is called when the ExternalTransform or
- // ClipShape of a facet on one this part's display frames
- // changes.
- //------------------------------------------------------------------------------
-
- void SoundEditor::GeometryChanged( Environment* ev,
- ODFacet* facet,
- ODBoolean clipShapeChanged,
- ODBoolean externalTransformChanged )
- {
- SOM_Trace("SoundEditor","GeometryChanged");
-
- if ( clipShapeChanged )
- // Specifying kODNULL means to invalidate the clipShape (which was
- // calculated from the usedShape).
- facet->Invalidate(ev, kODNULL, kODNULL);
- }
-
- //------------------------------------------------------------------------------
- // Method: HighlightChanged
- // Origin: ODPart
- //
- // Description: This method is called when a facet's hilighting state has been
- // changed (i.e. an icon view is now open and so should show the
- // icon in the open state).
- //------------------------------------------------------------------------------
-
- void SoundEditor::HighlightChanged(Environment* ev, ODFacet* facet)
- {
- ODFrame* frame = facet->GetFrame(ev);
-
- // The frame view has no "special" drawing characteristics
- // when opened or selected, so we don't need to update our
- // content.
-
- if ( frame->GetViewType(ev) != gGlobals->fFrameView )
- frame->Invalidate(ev, kODNULL, kODNULL);
- }
-
- //==============================================================================
- #pragma mark • Activation •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: BeginRelinquishFocus
- // Origin: ODPart
- //
- // Description: This method is called when another part (or possibly
- // ourself) is requesting a focus for one of its display
- // frames. Returning true means we are willing to give
- // up the requested focus.
- //
- // The part willingly gives up any focus unless:
- // it is the modal focus which we don't want to give up
- // until we are completely done displaying a modal dialog or
- // it is the sound in/out focus and we are recording/playing.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::BeginRelinquishFocus( Environment* ev,
- ODTypeToken focus,
- ODFrame* ownerFrame,
- ODFrame* proposedFrame )
- {
- SOM_Trace("SoundEditor","BeginRelinquishFocus");
-
- ODBoolean willRelinquish = kODTrue;
-
- // Another part is trying to put up a Modal dialog while we
- // are currently displaying ours. Deny the request.
- if ( focus == gGlobals->fModalFocus )
- {
- TempODPart proposedPart = ODAcquirePart(ev,proposedFrame);
- if ( ODObjectsAreEqual(ev, proposedPart, fSelf) == kODFalse )
- willRelinquish = kODFalse;
- }
-
- // Another part is trying to play a sound while we
- // are currently playing ours. Deny the request.
- if ( focus == gGlobals->fSoundOutFocus && this->SoundPlaying() )
- willRelinquish = kODFalse;
-
- // Another part is trying to record a sound while we
- // are currently recording ours. Deny the request.
- if ( focus == gGlobals->fSoundInFocus && this->SoundRecording() )
- willRelinquish = kODFalse;
-
- return willRelinquish;
- }
-
- //------------------------------------------------------------------------------
- // Method: CommitRelinquishFocus
- // Origin: ODPart
- //
- // Description: This method is called when it is actually time to give
- // up a focus that had been requested by another part (or
- // possibly ourself).
- //
- // The part calls its FocusLost method to handle the
- // "reliquishing" of the particular focus.
- //------------------------------------------------------------------------------
-
- void SoundEditor::CommitRelinquishFocus( Environment* ev,
- ODTypeToken focus,
- ODFrame* ownerFrame,
- ODFrame* proposedFrame )
- {
- SOM_Trace("SoundEditor","CommitRelinquishFocus");
-
- // We agreed to give up our FocusSet and now we are being asked to do so.
- this->FocusLost(ev, focus, ownerFrame);
- }
-
- //------------------------------------------------------------------------------
- // Method: AbortRelinquishFocus
- // Origin: ODPart
- //
- // Description: This method is called when another part (or possibly
- // ourself) requested a focus for one of its display
- // frames, but we returned kODFalse from
- // BeginRelinqishFocus for one, or all, of the requested
- // focus. At this point, we are being told to resume
- // ownership of the focus.
- //
- // The part calls its FocusAcquired method to handle the
- // re-"acquisition" of the particular focus.
- //------------------------------------------------------------------------------
-
- void SoundEditor::AbortRelinquishFocus( Environment* ev,
- ODTypeToken focus,
- ODFrame* ownerFrame,
- ODFrame* proposedFrame )
- {
- SOM_Trace("SoundEditor","AbortRelinquishFocus");
-
- // Some parts may have suspended some actions in the BeginRelinquishFocus
- // method. If so, they would resume those actions here.
- }
-
- //------------------------------------------------------------------------------
- // Method: FocusAcquired
- // Origin: ODPart
- //
- // Description: This method is called when the Arbitrator has
- // registered us as the "owner" of a particular focus.
- // This can occur if a focus is transfered to one of the part's
- // display frames.
- //
- // The part will request the other foci it needs to be "active". If
- // the part is successful, we notify ourself to become active.
- //------------------------------------------------------------------------------
-
- void SoundEditor::FocusAcquired( Environment* ev,
- ODTypeToken focus,
- ODFrame* ownerFrame )
- {
- SOM_Trace("SoundEditor","FocusAcquired");
-
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
-
- if ( gGlobals->fUIFocusSet->Contains(ev, focus) )
- {
- if ( arbitrator->RequestFocusSet(ev, gGlobals->fUIFocusSet, ownerFrame) )
- this->PartActivated(ev, ownerFrame);
- }
- else if ( focus == gGlobals->fSoundOutFocus )
- {
- if ( !fPlayer->Initialize() )
- this->DoDialogBox(ev, ownerFrame, kErrorBoxID, kErrCannotInitSndChannel);
- }
- else if ( focus == gGlobals->fSoundInFocus )
- {
- fRecorder->Initialize();
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: FocusLost
- // Origin: ODPart
- //
- // Description: This method is called when the Arbitrator has
- // unregistered us as the "owner" of the particular
- // focus.
- //
- // The part unmarks the active frame if the selection
- // focus is lost.
- //------------------------------------------------------------------------------
-
- void SoundEditor::FocusLost( Environment* ev,
- ODTypeToken focus,
- ODFrame* ownerFrame )
- {
- SOM_Trace("SoundEditor","FocusLost");
-
- if ( focus == gGlobals->fSelectionFocus )
- {
- CFrameInfo* frameInfo = (CFrameInfo*) ownerFrame->GetPartInfo(ev);
- frameInfo->SetFrameActive(kODFalse);
- }
- else if ( focus == gGlobals->fSoundOutFocus )
- {
- fPlayer->DeInitialize();
- }
- else if ( focus == gGlobals->fSoundInFocus )
- {
- fRecorder->DeInitialize();
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: RelinquishAllFoci
- // Origin: SoundEditor
- //
- // Description: This method is called when a frame is going away. The method
- // relinquishes all foci the frame owns.
- //------------------------------------------------------------------------------
-
- void SoundEditor::RelinquishAllFoci( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","RelinquishAllFoci");
-
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
-
- // Make sure the frame going away does own any foci. Forgetting
- // to do this, will cause a "refcounting" error when the frame
- // is deleted by the draft.
- TRY
- TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSelectionFocus);
- if ( ODObjectsAreEqual(ev, focusFrame, frame) )
- {
- arbitrator->RelinquishFocus(ev, gGlobals->fSelectionFocus, frame);
- this->FocusLost(ev, gGlobals->fSelectionFocus, frame);
- }
- CATCH_ALL
- ENDTRY
-
- TRY
- TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
- if ( ODObjectsAreEqual(ev, focusFrame, frame) )
- {
- arbitrator->RelinquishFocus(ev, gGlobals->fMenuFocus, frame);
- this->FocusLost(ev, gGlobals->fMenuFocus, frame);
- }
- CATCH_ALL
- ENDTRY
-
- TRY
- TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fKeyFocus);
- if ( ODObjectsAreEqual(ev, focusFrame, frame) )
- {
- arbitrator->RelinquishFocus(ev, gGlobals->fKeyFocus, frame);
- this->FocusLost(ev, gGlobals->fKeyFocus, frame);
- }
- CATCH_ALL
- ENDTRY
-
- TRY
- TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSoundOutFocus);
- if ( ODObjectsAreEqual(ev, focusFrame, frame) )
- {
- arbitrator->RelinquishFocus(ev, gGlobals->fSoundOutFocus, frame);
- this->FocusLost(ev, gGlobals->fSoundOutFocus, frame);
- }
- CATCH_ALL
- ENDTRY
-
- TRY
- TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, gGlobals->fSoundInFocus);
- if ( ODObjectsAreEqual(ev, focusFrame, frame) )
- {
- arbitrator->RelinquishFocus(ev, gGlobals->fSoundInFocus, frame);
- this->FocusLost(ev, gGlobals->fSoundInFocus, frame);
- }
- CATCH_ALL
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: PartActivated
- // Origin: SoundEditor
- //
- // Description: This method is called when the part gets activated (by
- // asking for the contents of its focus set or having focus
- // transferred to it).
- //------------------------------------------------------------------------------
-
- void SoundEditor::PartActivated( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","PartActivated");
-
- // We are required to re-validate the menubar before displaying it because
- // any part can/could swap the base menubar at any time.
- if ( !gGlobals->fMenuBar->IsValid(ev) )
- this->BuildMenuBar(ev);
-
- // Display our menu bar.
- gGlobals->fMenuBar->Display(ev);
-
- // And set our "active" state.
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
- frameInfo->SetFrameActive(kODTrue);
- }
-
- //------------------------------------------------------------------------------
- // Method: ActivateFrame
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a kODEvtMouseUp
- // occurs in an inactive frame in an active window, and
- // when an OpenDoc document comes forward.
- //
- // The part activates the frame by requesting the
- // UIFocusSet (created in Initialize) and by calling
- // FocusAcquired if we were successful. The method
- // returns true if no problems were encountered as a
- // signal to the caller that the frame is now "active".
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::ActivateFrame( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","ActivateFrame");
-
- ODBoolean activated = kODFalse;
-
- // Request the set of foci necessary to become active.
- if ( fSession->GetArbitrator(ev)
- ->RequestFocusSet(ev, gGlobals->fUIFocusSet, frame) )
- {
- // Activate the part.
- this->PartActivated(ev, frame);
- // We were able to become active.
- activated = kODTrue;
- }
-
- return activated;
- }
-
- //------------------------------------------------------------------------------
- // Method: WindowActivating
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a window activation
- // event (kODEvtActivate) occurs.
- //
- // The part remembers the frame's active state and restores it when
- // events come in. If the frame is active and the window is being
- // sent into the background, remember to reactivate the part when
- // the window is reactivated.
- //------------------------------------------------------------------------------
-
- void SoundEditor::WindowActivating( Environment* ev,
- ODFrame* frame,
- ODBoolean activating )
- {
- SOM_Trace("SoundEditor","WindowActivating");
-
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // The window is being activated and we had the selection focus when
- // the window was deactivated, so request it again.
- if ( activating && frameInfo->FrameNeedsReactivating() )
- {
- this->ActivateFrame(ev, frame);
- frameInfo->SetFrameReactivate(kODFalse);
- }
- // The window is being deactivated and we have the active part.
- // So give up our foci and remind ourselves that we need to request
- // the focus when the window is reactivated.
- else if ( !activating && frameInfo->IsFrameActive() )
- {
- frameInfo->SetFrameReactivate(kODTrue);
- }
- }
-
- //==============================================================================
- #pragma mark • Event Handling •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: HandleEvent
- // Origin: ODPart
- //
- // Description: The method is called when an event, which falls into
- // the category of an owned focus, occurs. The two
- // exceptions to this are "mouse movement" events and
- // embedded frame events, which can occur when a part
- // owns no foci.
- //
- // The part returns true if the event was handled.
- //------------------------------------------------------------------------------
-
-
- ODBoolean SoundEditor::HandleEvent( Environment* ev,
- ODEventData* event,
- ODFrame* frame,
- ODFacet* facet,
- ODEventInfo* eventInfo )
- {
- SOM_Trace("SoundEditor","HandleEvent");
-
- ODBoolean eventHandled = kODFalse;
-
- // Event handling is basically the same as standard Macintosh applications,
- // except that the events have been renamed for cross-platform compatability.
-
- switch ( event->what )
- {
- case kODEvtNull:
- if ( this->SoundDonePlaying(ev) )
- {
- // if the length was unknown before playing
- // we now know the length of the sound if it
- // stopped because it ended.
- if ( fUnknownSound )
- fSecsRecorded = -fSecsRecorded;
-
- this->StopPlayingSound(ev);
- }
- if ( this->SoundDoneRecording(ev) )
- this->StopRecordingSound(ev);
- eventHandled = kODTrue;
- break;
-
- case kODEvtMouseDown:
- case kODEvtMouseUp:
- eventHandled = this->HandleMouseEvent(ev, event, facet, eventInfo);
- break;
-
- case kODEvtMenu:
- eventHandled = this->HandleMenuEvent(ev, event, frame);
- break;
-
- case kODEvtKeyDown:
- eventHandled = this->HandleKeyboardEvent(ev, event, frame);
- break;
-
- case kODEvtActivate:
- // We are being notified that a window we are displayed in has
- // just been de/activated (un/hilighted).
- this->WindowActivating(ev, frame, (event->modifiers & activeFlag));
- eventHandled = kODTrue;
- break;
-
- case kODEvtMouseEnter:
- case kODEvtMouseLeave:
- SetCursor(&ODQDGlobals.arrow);
- eventHandled = kODTrue;
- break;
-
- case kODEvtMouseWithin:
- eventHandled = kODTrue;
- break;
-
- // Other events a part might handle
- case kODEvtMouseDownEmbedded:
- case kODEvtMouseUpEmbedded:
- case kODEvtMouseDownBorder:
- case kODEvtMouseUpBorder:
- case kODEvtWindow:
- case kODEvtKeyUp:
- case kODEvtAutoKey:
- case kODEvtDisk:
- case kODEvtOS:
-
- default:
- break;
- }
-
- return eventHandled;
- }
-
- //------------------------------------------------------------------------------
- // Method: BuildMenuBar
- // Origin: SoundEditor
- //
- // Description: This method is called when the menubar needs to be created or
- // changed (because it has become invalid).
- //------------------------------------------------------------------------------
-
- void SoundEditor::BuildMenuBar( Environment* ev )
- {
- if (gGlobals->fMenuBar == kODNULL || !gGlobals->fMenuBar->IsValid(ev))
- {
- ODBoolean changingBaseMenuBar = (gGlobals->fMenuBar != kODNULL);
-
- if (changingBaseMenuBar)
- {
- // Remove our menus from the old menubar.
- for (ODSShort index = 0; index < kNumMenus; index++)
- {
- ODSShort id = kBaseMenuID + index;
- gGlobals->fMenuBar->RemoveMenu(ev, id);
- }
- }
-
- ODFinalReleaseObject(ev, gGlobals->fMenuBar);
-
- // It is required that parts instantiate their menu bars from
- // the base OpenDoc menu bar. This maintains consistency in the
- // default menu items and their placement.
- // Since the object is a copy, we can add and subtract menus and
- // items without affecting other running parts.
- gGlobals->fMenuBar = fSession->GetWindowState(ev)->CopyBaseMenuBar(ev);
-
- // Add our resource-based menus and register all the editor specific
- // command numbers.
- CUsingLibraryResources res;
- for (ODSShort index = 0; index < kNumMenus; index++)
- {
- ODSShort id = kBaseMenuID + index;
-
- MenuHandle menu = GetMenu(id);
- if (menu != kODNULL)
- gGlobals->fMenuBar->AddMenuLast(ev, id, menu, fSelf);
- }
-
- gGlobals->fMenuBar->RegisterCommand(ev, kPlayCommand, kSoundMenuID, 1);
- gGlobals->fMenuBar->RegisterCommand(ev, kPauseCommand, kSoundMenuID, 2);
- gGlobals->fMenuBar->RegisterCommand(ev, kStopCommand, kSoundMenuID, 3);
- gGlobals->fMenuBar->RegisterCommand(ev, kRecordCommand, kSoundMenuID, 4);
- gGlobals->fMenuBar->RegisterCommand(ev, kSettingsCommand, kSoundMenuID, 6);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: AdjustMenus
- // Origin: ODPart
- //
- // Description: This method is called when a kODEvtMouseDown event
- // occurs in the menubar and the part owns the "menu"
- // focus or it is the root part of the window with the active
- // part.
- //
- // The part enables the appropriate items for its current
- // state and updates the menu items to reflect this
- // editor.
- //------------------------------------------------------------------------------
-
- void SoundEditor::AdjustMenus( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","AdjustMenus");
-
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
-
- // The menubar object always calls the root part's AdjustMenus method before
- // calling the menu focus owner's. Because of this, we need to validate the
- // menubar in the case where we are the root part.
- if ( frame->IsRoot(ev) )
- {
- // We are required to re-validate the menubar before displaying it because
- // any part can/could swap the base menubar at any time.
- if ( !gGlobals->fMenuBar->IsValid(ev) )
- this->BuildMenuBar(ev);
- }
-
- // En/disable the stop and play commands accordingly.
- // Also check/uncheck the pause menu item
-
- gGlobals->fMenuBar->EnableCommand(ev, kPlayCommand, this->IsPlayAvailable());
- gGlobals->fMenuBar->CheckCommand(ev, kPlayCommand, this->SoundPlaying());
-
- gGlobals->fMenuBar->EnableCommand(ev, kPauseCommand, this->IsPauseAvailable());
- gGlobals->fMenuBar->CheckCommand(ev, kPauseCommand, this->SoundPaused());
-
- gGlobals->fMenuBar->EnableCommand(ev, kStopCommand, this->IsStopAvailable());
-
- gGlobals->fMenuBar->EnableCommand(ev, kRecordCommand, this->IsRecordAvailable());
- gGlobals->fMenuBar->CheckCommand(ev, kRecordCommand, this->SoundRecording());
-
- // En/disable the edit commands accordingly.
-
- ODBoolean isBusy = (this->SoundPlaying() || this->SoundRecording());
- ODBoolean canCopy = (fPlayer->HasSound() && !isBusy);
- gGlobals->fMenuBar->EnableCommand(ev, kODCommandCopy, canCopy);
-
- ODBoolean canCut = (canCopy && !fReadOnlyStorage);
- gGlobals->fMenuBar->EnableCommand(ev, kODCommandCut, canCut);
- gGlobals->fMenuBar->EnableCommand(ev, kODCommandClear, canCut);
-
- TRY
- ODBoolean canPaste = ((!fReadOnlyStorage && this->SoundOnClipboard(ev, frame))
- && !isBusy);
- gGlobals->fMenuBar->EnableCommand(ev, kODCommandPaste, canPaste);
- CATCH_ALL
- // Consume exception.
- ENDTRY
-
- // Enable the "Settings" command.
- gGlobals->fMenuBar->EnableCommand(ev, kSettingsCommand, !this->SoundRecording());
-
- // Enable the "View As Window" command.
- gGlobals->fMenuBar->EnableCommand(ev, kODCommandViewAsWin, !frame->IsRoot(ev));
-
- // Load menu item names.
- TRY
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
- TempODFrame menuOwner = arbitrator->AcquireFocusOwner(ev, gGlobals->fMenuFocus);
-
- // There is no need to load a resource, create an ODIText object, set the menubar,
- // and cleanup, if we don't own the menu focus.
- if ( ODObjectsAreEqual(ev, frame, menuOwner) )
- {
- // Change the "About" menu item text for our part.
- Str63 text;
- ODGetIndString(text, kMenuStringResID, kAboutTextID);
-
- TempODIText menuItem = CreateIText(gGlobals->fEditorsScript,
- gGlobals->fEditorsLanguage,
- (StringPtr) &text);
- gGlobals->fMenuBar->SetItemString(ev, kODCommandAbout, menuItem);
-
- // Set the resource file so our balloon help menu items will appear.
- WASSERT(fMenuSavedResFile == -1);
- fMenuSavedResFile = BeginUsingLibraryResources();
- }
- CATCH_ALL
- // Consume exception.
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: HandleMenuEvent
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a menu event is
- // received.
- //
- // Using the menu bar object, we determine what the menu
- // command is, and call the appropriate method to handle it.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::HandleMenuEvent( Environment* ev,
- ODEventData* event,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","HandleMenuEvent");
-
- // Restore the previous resource file.
- if ( fMenuSavedResFile != -1 )
- {
- EndUsingLibraryResources(fMenuSavedResFile);
- fMenuSavedResFile = -1;
- }
-
- ODULong menuResult = event->message;
- ODUShort menu = HiWord(menuResult);
- ODUShort item = LoWord(menuResult);
- ODCommandID command = gGlobals->fMenuBar->GetCommand(ev, menu, item);
-
- if ( this->HandleSoundEvent(ev, command) )
- return kODTrue;
-
- switch ( command )
- {
- case kSettingsCommand:
- this->ShowSettingsDialog(ev, frame);
- break;
-
- // --- OpenDoc commands ---
-
- case kODCommandAbout:
- this->DoDialogBox(ev, frame, kAboutBoxID);
- break;
-
- case kODCommandViewAsWin:
- this->Open(ev, frame);
- break;
-
- case kODCommandCut:
- case kODCommandCopy:
- this->CopySound(ev, frame);
- this->AnnotateClipboard(ev, frame);
-
- if ( command == kODCommandCut )
- this->ClearSound(ev, frame);
- break;
-
- case kODCommandPaste:
- this->PasteSound(ev, frame);
- break;
-
- case kODCommandClear:
- this->ClearSound(ev, frame);
- break;
-
- // Other commands a part might handle
- case kODCommandOpen:
- case kODCommandInsert:
- case kODCommandPageSetup:
- case kODCommandPrint:
- case kODCommandUndo:
- case kODCommandRedo:
- case kODCommandPasteAs:
- case kODCommandSelectAll:
- case kODCommandGetPartInfo:
- case kODCommandPreferences:
-
- default:
- return kODFalse;
- }
-
- return kODTrue;
- }
-
-
-
- //--------------------------------------------------------------------
- // Method: HandleKeyboardEvent
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a keyboard
- // event is recieved.
- //
- // The editor supports playing the recorded sound by
- // hitting the space bar.
- //-------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::HandleKeyboardEvent( Environment* ev,
- ODEventData* event,
- ODFrame* frame )
- {
- const long kSpaceBar = 0x20L;
-
- SOM_Trace("SoundEditor","HandleKeyboardEvent");
-
- ODBoolean handled = kODFalse;
-
- // If the controls palette is showing and the user hits the space
- // bar, stop playing the sound if something is playing,
- // stop recording a sound if something is recording,
- // or start playing the sound otherwise
-
- if ( frame->GetViewType(ev) == gGlobals->fFrameView &&
- frame->GetPresentation(ev) == gGlobals->fControlsPresentation )
- {
- if ( (event->message & charCodeMask) == kSpaceBar )
- {
- if ( this->SoundPlaying() )
- this->StopPlayingSound(ev);
-
- else if ( this->SoundRecording() )
- this->StopRecordingSound(ev);
-
- else
- this->PlaySound(ev);
-
- handled = kODTrue;
- }
- }
-
- return handled;
- }
-
- //------------------------------------------------------------------------------
- // Method: HandleMouseEvent
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a mouse event
- // is recieved.
- //
- // A typical part would determine the event type(up/down)
- // and respond appropriately, but we have no "real"
- // content model, so we activate the part as appropriate
- // and call a generic method to handle the event.
- //
- // Remember: When a frame is inactive, the first mouse up event
- // should activate it; inactive frames do not recieve
- // kODEvtMouseDown events.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::HandleMouseEvent( Environment* ev,
- ODEventData* event,
- ODFacet* facet,
- ODEventInfo* eventInfo )
- {
- SOM_Trace("SoundEditor","HandleMouseEvent");
-
- // If the facet parameter is invalid, the mouse up occurred outside the
- // bounds of a Modal window, otherwise it should be treated normally.
-
- ODBoolean result = kODTrue;
- ODFrame* frame = facet->GetFrame(ev);
-
- if ( facet != kODNULL )
- {
- if ( event->what == kODEvtMouseUp )
- {
- // Handle the mouse up event.
- result = this->DoMouseUp(ev, event, facet, eventInfo);
- }
- else if ( event->what == kODEvtMouseDown )
- {
- // Handle the mouse down event.
- this->DoMouseDown(ev, event, facet, eventInfo);
- }
- }
- else
- {
- // User clicked outside the bounds of a Modal window.
- SysBeep(1);
- }
-
- return result;
- }
-
- //------------------------------------------------------------------------------
- // Method: DoMouseUp
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a mouse event
- // is recieved.
- //
- // If the user mouses up in the sound controls palette
- // over an active button, perform the action (record,
- // play, stop).
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::DoMouseUp( Environment* ev,
- ODEventData* event,
- ODFacet* facet,
- ODEventInfo* eventInfo )
- {
- SOM_Trace("SoundEditor","DoMouseUp");
-
- ODWindow* window = facet->GetWindow(ev);
-
- if ( !window->IsActive(ev) )
- {
- // Activate inactive windows on the first mouse up event.
- window->Select(ev);
- }
- else
- {
- // Activate the frame (if needed) on all subsequent mouse up events.
- ODFrame* frame = facet->GetFrame(ev);
-
- // Get our state information from the PartInfo of the frame.
- CFrameInfo* frameInfo = (CFrameInfo*) frame->GetPartInfo(ev);
-
- // If this frame is not the active one, activate it by requesting
- // the appropriate foci.
-
- if ( !frameInfo->IsFrameActive() )
- {
- if ( this->ActivateFrame(ev, frame) )
- // Keep track of which facet was the last active for positioning
- // part windows.
- frameInfo->SetActiveFacet(facet);
- else
- // We were unable to acquire the necessary focus and activate it.
- return kODFalse;
- }
-
- // No do any other action that would be appropriate for a mouse up
- // event.
- }
-
- return kODTrue;
- }
-
- //------------------------------------------------------------------------------
- // Method: DoMouseDown
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a mouse event
- // is recieved.
- //
- // If the facet is displaying the sound controls palette,
- // we handle mouse downs on the buttons.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DoMouseDown( Environment* ev,
- ODEventData* event,
- ODFacet* facet,
- ODEventInfo* eventInfo )
- {
- SOM_Trace("SoundEditor","DoMouseDown");
-
- EButton button = kNoButton;
- ODFrame* frame = facet->GetFrame(ev);
-
- // If the mouse down occurred in a active frame in an active
- // window, see if the control palette is displayed and
- // respond to the click; otherwise, just ignore the event.
-
- if ( frame->GetViewType(ev) == gGlobals->fFrameView )
- {
- EButtonState initialState = kButtonStateNormal;
-
- Point where;
-
- // Get the localized mouse coordinates from the Event Info.
- where.h = FixedToInt(eventInfo->where.x);
- where.v = FixedToInt(eventInfo->where.y);
-
- // Record button is only disabled when there
- // is something recording and not paused
- // or if the draft is read-only
- if ( PtInRect(where, &gGlobals->fButtonRect[kRecordButton])
- && this->IsRecordAvailable() )
- {
- button = kRecordButton;
- if ( this->SoundRecording() )
- initialState = kButtonStateOn;
- }
-
- // Stop button is only enabled when there
- // is something to stop (record or play)
- else if ( PtInRect(where, &gGlobals->fButtonRect[kStopButton])
- && this->IsStopAvailable() )
- {
- button = kStopButton;
- }
-
- // Pause button is only enabled when there
- // is something to pause (record or play)
- else if ( PtInRect(where, &gGlobals->fButtonRect[kPauseButton])
- && this->IsPauseAvailable() )
- {
- button = kPauseButton;
- if ( this->SoundPaused() )
- initialState = kButtonStateOn;
- }
-
- // Play button is only enabled when there is something playing and paused,
- // or if nothing is playing or recording
- else if ( PtInRect(where, &gGlobals->fButtonRect[kPlayButton])
- && this->IsPlayAvailable() )
- {
- button = kPlayButton;
- if ( this->SoundPlaying() )
- initialState = kButtonStateOn;
- }
-
- CUsingLibraryResources res;
-
- // Handle tracking if a button was hit.
- CFocus initiateDrawing(ev, facet);
- if (button != kNoButton && this->TrackButton(ev, button, where, initialState))
- {
- ODFrame* frame = facet->GetFrame(ev);
-
- // Handle clicking in palette buttons
-
- switch (button)
- {
- case kRecordButton:
- this->HandleSoundEvent(ev, kRecordCommand);
- break;
-
- case kStopButton:
- this->HandleSoundEvent(ev, kStopCommand);
- break;
-
- case kPlayButton:
- this->HandleSoundEvent(ev, kPlayCommand);
- break;
-
- case kPauseButton:
- this->HandleSoundEvent(ev, kPauseCommand);
- break;
- }
-
- // Invalidate the button that was pressed.
- // Change the button appearance to button down or up (not pressed)
-
- this->InvalidateButton(ev, button);
- }
- else // Mouse released outside button or button not hit.
- {
- if ( button == kPauseButton || button == kPlayButton )
- this->InvalidateButton(ev, button);
- // This is done because the track call will leave the button
- // in an up state if it was tracked out of, but in this case,
- // the pause button may have been left on.
- }
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: HandleSoundEvent
- // Origin: SoundEditor
- //
- // Description: This method is called by the part to handle window events.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::HandleSoundEvent( Environment* ev,
- ODCommandID command )
- {
- switch ( command )
- {
- case kPlayCommand:
- if ( fPlayer->IsPaused() )
- this->ResumePlayingSound(ev);
- else
- this->PlaySound(ev);
- break;
-
- case kPauseCommand:
- if ( this->SoundPlaying() )
- {
- if ( fPlayer->IsPaused() )
- this->ResumePlayingSound(ev);
- else
- this->PausePlayingSound(ev);
- }
-
- if ( this->SoundRecording() )
- {
- if ( fRecorder->IsPaused() )
- this->ResumeRecordingSound(ev);
- else
- this->PauseRecordingSound(ev);
- }
- break;
-
- case kStopCommand:
- if ( this->SoundPlaying() )
- this->StopPlayingSound(ev);
-
- if ( this->SoundRecording() )
- this->StopRecordingSound(ev);
- break;
-
- case kRecordCommand:
- if ( this->SoundRecording() && fRecorder->IsPaused() )
- this->ResumeRecordingSound(ev);
- else if ( !fReadOnlyStorage )
- this->RecordSound(ev);
- break;
-
- default:
- return kODFalse;
- }
-
- return kODTrue;
- }
-
- //------------------------------------------------------------------------------
- // Method: DoDialogBox
- // Origin: SoundEditor
- //
- // Description: This method is called by the part when a dialog needs to be
- // displayed (e.g. the About Box). If a valid error number is
- // passed in, an error dialog will be displayed.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DoDialogBox( Environment* ev,
- ODFrame* frame,
- ODSShort dialogID,
- ODUShort errorNumber )
- {
- SOM_Trace("SoundEditor","DoDialogBox");
-
- // If the calling method does not have a frame available to it, we need to
- // locate a frame to use for requesting the modal focus. Find the first valid
- // frame in our display frames list.
- ODFrame* focusFrame = frame;
- if ( focusFrame == kODNULL )
- focusFrame = this->FindFirstAvailableFrame(ev);
-
- // Our dialog boxes are modal so we must request the Modal focus to prevent
- // multiple modal dialogs being displayed simultaneously.
-
- TempFocus modalFocus(ev, gGlobals->fModalFocus, focusFrame);
- if ( modalFocus.Request() )
- {
- // Dim the frontmost document window.
- fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
-
- CUsingLibraryResources res;
-
- DialogPtr dialog = GetNewDialog(dialogID, kODNULL, (WindowPtr) -1L);
- if ( dialog )
- {
- if ( errorNumber > 0 )
- {
- Handle itemHandle;
- Rect itemRect;
- short itemType;
- Str255 errStr;
-
- ODGetIndString(errStr, kErrorStringResID, errorNumber);
- GetDialogItem(dialog, kErrStrFieldID, &itemType, &itemHandle, &itemRect);
- SetDialogItemText(itemHandle, errStr);
-
- // We don't need the cancel button for an error dialog.
- HideDialogItem(dialog, cancel);
-
- SetDialogDefaultItem(dialog, ok);
- }
-
- ShowWindow(dialog);
- SetCursor(&ODQDGlobals.arrow);
-
- ODSShort itemHit;
- ModalDialog(kODNULL, &itemHit);
-
- DisposeDialog(dialog);
- }
- else
- {
- // Could not load dialog... something is amiss.
- SysBeep(2);
- }
-
- // Hilite the frontmost document window.
- fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
- }
- else
- {
- // If we can't get the modal focus, then another modal dialog is
- // already being displayed.
- SysBeep(2);
- }
- }
-
- //==============================================================================
- #pragma mark • Extensions •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: HasExtension
- // Origin: ODPart
- //
- // Description: The method is called when something wants to know if this
- // part supports a particular type of extension.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::HasExtension( Environment* ev,
- ODType extensionName )
- {
- SOM_Trace("SoundEditor","HasExtension");
-
- return ( ODISOStrEqual(extensionName, kODSettingsExtension)
- || ODISOStrEqual(extensionName, kODExtSemanticInterface) );
- }
-
- //------------------------------------------------------------------------------
- // Method: AcquireExtension
- // Origin: ODPart
- //
- // Description: The method is called when the part is being asked for
- // a particular extension.
- //------------------------------------------------------------------------------
-
- ODExtension* SoundEditor::AcquireExtension( Environment* ev,
- ODType extensionName )
- {
- SOM_Trace("SoundEditor","AcquireExtension");
-
- if ( ODISOStrEqual(extensionName, kODSettingsExtension) )
- {
- if ( fSettingsExtension == kODNULL )
- {
- fSettingsExtension = new som_SESettingsExtension;
- THROW_IF_NULL(fSettingsExtension);
- fSettingsExtension->InitSettingsExtension(ev, fSelf);
- }
-
- ODAcquireObject(ev, fSettingsExtension);
- return fSettingsExtension;
- }
- else if ( ODISOStrEqual(extensionName, kODExtSemanticInterface) )
- {
- if ( fSemIntf == kODNULL )
- {
- // Instantiate the semantic interface extension and helper objects
- fSemIntf = new SoundEditorSI;
- THROW_IF_NULL(fSemIntf);
- fSemIntf->InitSemanticInterface(ev, fSelf, fSession);
- fSemIntf->RegisterRealPart(ev, this);
- }
-
- ODAcquireObject(ev, fSemIntf);
- return fSemIntf;
- }
- else
- {
- return kODNULL;
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ReleaseExtension
- // Origin: ODPart
- //
- // Description: The method is called when the last instance of an extension
- // belonging to this part has been released.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::ReleaseExtension( Environment* ev,
- ODExtension* extension )
- {
- SOM_Trace("SoundEditor","ReleaseExtension");
-
- if ( ODObjectsAreEqual(ev, extension, fSettingsExtension) )
- {
- ODDeleteObject(fSettingsExtension);
- return kODTrue;
- }
- else if ( ODObjectsAreEqual(ev, extension, fSemIntf) )
- {
- ODDeleteObject(fSemIntf);
- return kODTrue;
- }
- else
- {
- return kODFalse;
- }
- }
-
- //==============================================================================
- #pragma mark • SoundEditor-specific •
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // Method: ShowSettingsDialog
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when the user chooses the
- // Settings menu item or clicks the Settings button in Part Info.
- //------------------------------------------------------------------------------
-
- void SoundEditor::ShowSettingsDialog( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","ShowSettingsDialog");
-
- TempFocus modalFocus(ev, gGlobals->fModalFocus, frame);
- if ( modalFocus.Request() )
- {
- // Dim the frontmost document window.
- fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
-
- DialogPtr dialog = kODNULL;
- ODVolatile(dialog);
-
- TRY
- CUsingLibraryResources res;
-
- dialog = GetNewDialog(kSettingsDialogID, kODNULL, (WindowPtr) -1L);
- THROW_IF_NULL(dialog);
-
- SetDialogDefaults(dialog, kDialogFontInfoID, 1);
-
- short itemType;
- Rect itemRect;
- ControlHandle goodButton;
- ControlHandle betterButton;
- ControlHandle bestButton;
-
- GetDialogItem(dialog, kGood, &itemType, (Handle*) &goodButton, &itemRect);
- GetDialogItem(dialog, kBetter, &itemType, (Handle*) &betterButton, &itemRect);
- GetDialogItem(dialog, kBest, &itemType, (Handle*) &bestButton, &itemRect);
-
- SetControlValue(goodButton, (fRecordingQuality == siGoodQuality));
- SetControlValue(betterButton, (fRecordingQuality == siBetterQuality));
- SetControlValue(bestButton, (fRecordingQuality == siBestQuality));
-
- SetCursor(&ODQDGlobals.arrow);
- ShowWindow(dialog);
-
- short itemHit;
- do
- {
- ModalDialog(kODNULL, &itemHit);
-
- switch ( itemHit )
- {
- case kGood:
- case kBetter:
- case kBest:
- {
- SetControlValue(goodButton, (itemHit == kGood));
- SetControlValue(betterButton, (itemHit == kBetter));
- SetControlValue(bestButton, (itemHit == kBest));
- }
- break;
- }
- }
- while ( itemHit != ok && itemHit != cancel );
-
- if ( itemHit == ok )
- {
- if ( GetControlValue(goodButton) )
- this->SetRecordingQuality(siGoodQuality);
- else if ( GetControlValue(betterButton) )
- this->SetRecordingQuality(siBetterQuality);
- else if ( GetControlValue(bestButton) )
- this->SetRecordingQuality(siBestQuality);
- }
-
- CATCH_ALL
- if (dialog)
- DisposeDialog(dialog);
-
- // Hilite the frontmost document window.
- fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
-
- RERAISE;
- ENDTRY
-
- DisposeDialog(dialog);
-
- // Hilite the frontmost document window.
- fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
- }
- }
-
- //------------------------------------------------------------------------------
-
- #pragma segment SoundEditorContentHandling
-
- //------------------------------------------------------------------------------
- // Method: PlaySound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when the Play button is enabled
- // and the user has clicked on it.
- //------------------------------------------------------------------------------
-
- void SoundEditor::PlaySound( Environment* ev)
- {
- SOM_Trace("SoundEditor","PlaySound");
-
- // If there is no sound to play, then return immediately
- if ( fPlayer->GetSound() == kODNULL )
- return;
-
- ODFrame* frame = this->FindFirstAvailableFrame(ev);
-
- // Request sound out focus
- if ( fSession->GetArbitrator(ev)
- ->RequestFocus(ev, gGlobals->fSoundOutFocus, frame) )
- {
- this->FocusAcquired(ev, gGlobals->fSoundOutFocus, frame);
- }
- else
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrEditorPlaying);
- return;
- }
-
- if ( !fPlayer->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- TRY
- // Play the sound.
- if ( fPlayer->Start(frame) )
- {
- fSession->GetDispatcher(ev)->
- RegisterIdle(ev, fSelf, frame, kSoundEditorIdle);
-
- this->InvalidateButton(ev, kRecordButton);
- this->InvalidateButton(ev, kStopButton);
- this->InvalidateButton(ev, kPauseButton);
- this->InvalidateButton(ev, kPlayButton);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fCurrentTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fSpeakerIconRect);
- }
- else
- {
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrCannotPlaySound);
- }
-
- CATCH_ALL
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrCannotPlaySound);
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: StopPlayingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::StopPlayingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","StopPlayingSound");
-
- if ( !fPlayer->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- ODBoolean wasPaused = fPlayer->IsPaused();
-
- if ( fPlayer->Stop() )
- {
- ODFrame* frame = this->FindFirstAvailableFrame(ev);
-
- fSession->GetArbitrator(ev)
- ->RelinquishFocus(ev, gGlobals->fSoundOutFocus, frame);
- this->FocusLost(ev, gGlobals->fSoundOutFocus, frame);
-
- // Stop checking the status of the sound channel.
- fSession->GetDispatcher(ev)->
- UnregisterIdle(ev, fSelf, frame);
-
- // Invalidate the play button to pop it back up
- this->InvalidateButton(ev, kRecordButton);
- this->InvalidateButton(ev, kStopButton);
- this->InvalidateButton(ev, kPauseButton);
- this->InvalidateButton(ev, kPlayButton);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fSpeakerIconRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fCurrentTimeRect);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: PausePlayingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::PausePlayingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","PausePlayingSound");
-
- if ( !fPlayer->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- if ( fPlayer->Pause() )
- {
- this->InvalidateButton(ev, kPauseButton);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fSpeakerIconRect);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ResumePlayingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::ResumePlayingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","ResumePlayingSound");
-
- if ( !fPlayer->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- if ( fPlayer->Resume() )
- {
- this->InvalidateButton(ev, kPauseButton);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fSpeakerIconRect);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: UpdateDisplay
- // Origin: SoundEditor
- //
- // Description: The method is called by the part while a sound is recording or
- // playing to update the progress bar, time indicator, and speaker
- // icon.
- //
- // This routine returns a boolean value indicating if the sounder
- // is completed. This must be done because of the implementation
- // of the sounder class, where IsCompleted is called to update
- // the time field.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::UpdateDisplay( Environment* ev, CSounder* sounder )
- {
- SOM_Trace("SoundEditor","UpdateDisplay");
-
- // If we don't need to do any drawing, just return.
- if ( sounder == fPlayer && sounder->IsPaused() )
- return kODFalse;
-
- ODULong oldTime = sounder->GetTime();
- // We have to get the old time before calling IsCompleted because
- // IsCompleted will update the time.
-
- ODBoolean done = sounder->IsCompleted();
-
- // We have to actually draw the progress bar, time, and meter here.
- // We can't just invalidate them because it will cause an awful flicker.
-
- fCurrentTime = sounder->GetTime();
-
- if (sounder == fPlayer)
- {
- if ( fUnknownSound ) // If sound has unknown length
- fSecsRecorded = -fCurrentTime; // use current value (as -)
- if ( fCurrentTime > fSecsRecorded )
- fCurrentTime = fSecsRecorded;
- }
- else
- {
- if ( fCurrentTime > fMaxSeconds )
- fCurrentTime = fMaxSeconds;
- }
-
- ODSShort progBar;
- if ( fMaxSeconds )
- progBar = (fCurrentTime * 100) / fMaxSeconds;
- else
- progBar = 0;
-
- // Iterate over the frames we are displayed through and determine which
- // ones we need to invalidate.
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- // If the display frame is real (has been "connected" or was "added")
- // get its view type; otherwise, ignore it.
- ODFrame* frame = proxy->GetFrame(ev);
- if ( frame != kODNULL
- && frame->GetPresentation(ev) == gGlobals->fControlsPresentation
- && frame->GetViewType(ev) == gGlobals->fFrameView )
- {
- for ( TempODFrameFacetIterator facet(ev, frame);
- facet.IsNotComplete(); facet.Next() )
- {
- if ( !sounder->IsPaused() )
- {
- this->DrawCurrentTime(ev, facet, oldTime, fCurrentTime);
- this->DrawProgressBar(ev, facet, progBar,
- (sounder == fPlayer) ? kPlayingPAT : kRecordOnPAT);
- }
-
- CFocus initiateDrawing(ev, facet);
- DrawEditorPicture(kSpeaker0PICT + sounder->GetLevel(),
- gGlobals->fSpeakerIconRect);
- }
- }
- }
-
- return done;
- }
-
- //------------------------------------------------------------------------------
- // Method: SoundDonePlaying
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::SoundDonePlaying( Environment* ev )
- {
- SOM_Trace("SoundEditor","SoundDonePlaying");
-
- if ( !this->SoundPlaying() )
- return kODFalse;
-
- return this->UpdateDisplay(ev, fPlayer);
- }
-
- //------------------------------------------------------------------------------
- // Method: RecordSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when it wants to start
- // recording a sound.
- //------------------------------------------------------------------------------
-
- void SoundEditor::RecordSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","RecordSound");
-
- ODFrame* frame = this->FindFirstAvailableFrame(ev);
-
- TRY
- // Record the sound.
-
- // Request sound in focus
- if ( fSession->GetArbitrator(ev)
- ->RequestFocus(ev, gGlobals->fSoundInFocus, frame) )
- {
- this->FocusAcquired(ev, gGlobals->fSoundInFocus, frame);
-
- // If the user is interupting the current sound being played,
- // then stop the sound before recording.
- if ( this->SoundPlaying() )
- this->StopPlayingSound(ev);
-
- this->InvalidateButton(ev, kRecordButton);
-
- Size grow;
- Size availableMemory = TempMaxMem(&grow);
-
- if ( availableMemory < 64 * 1024 )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrOutOfMemory);
- return;
- }
-
- // Make sure there is at least one 32k contiguous block of memory.
- // This helps prevent spurious "out of memory" errors in the toolbox.
- if ( availableMemory >= (32768 + fMaxMemory) )
- availableMemory = fMaxMemory;
- else
- availableMemory -= 32768;
-
- // Using OpenDoc's memory mgr, allocate a buffer in temp memory.
- ODHandle tempHandle = ODNewHandle(availableMemory);
- fRecorder->SetSound(tempHandle);
-
- // If an asynchronous sound device can be opened, do asynchronous recording
- fRecorder->SetQuality(fRecordingQuality);
- if ( fRecorder->Start(frame) )
- {
- fMaxSeconds = fRecorder->GetMaxTime(availableMemory, fRecordingQuality);
-
- fSession->GetDispatcher(ev)->
- RegisterIdle(ev, fSelf, frame, kSoundEditorIdle);
-
- // no need to invalidate buttons - "record on" button already drawn above
- this->InvalidateButton(ev, kStopButton);
- this->InvalidateButton(ev, kPauseButton);
- this->InvalidateButton(ev, kPlayButton);
-
- // do need to update the max time and the progress bar to record though
- this->InvalidateFrameViewRect(ev, gGlobals->fCurrentTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fMaxTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
- }
- else
- {
- // unable to open asynchronous sound device use the modal window instead
- TempFocus modalFocus(ev, gGlobals->fModalFocus, frame);
- TempFocus soundInFocus(ev, gGlobals->fModalFocus, frame);
-
- if ( modalFocus.Request() && soundInFocus.Request() )
- {
- Rect scratchRect;
- SetRect(&scratchRect, 0, 0, 10, 10);
- this->CalcPartWindowPosition(ev, frame, &scratchRect);
-
- Point topLeft;
- topLeft.v = scratchRect.top;
- topLeft.h = scratchRect.left;
-
- // Dim the frontmost document window.
- fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
-
- // Record sound using Standard Record dialog provided by the Sound Mgr.
- OSErr error = SndRecord(kODNULL, topLeft, fRecordingQuality,
- (SndListHandle*) &tempHandle);
-
- // Hilite the frontmost document window.
- fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
-
- // Invalidate the record button to pop it back up
- this->InvalidateButton(ev, kRecordButton);
- this->InvalidateButton(ev, kStopButton);
- this->InvalidateButton(ev, kPauseButton);
- this->InvalidateButton(ev, kPlayButton);
-
- // If all went well, save the newly recorded sound.
- if ( error != userCanceledErr )
- {
- THROW_IF_ERROR(error);
-
- fPlayer->SetSound(tempHandle);
- if (fPreferredKind == kODNullTypeToken)
- fPreferredKind = gGlobals->fNativeData;
-
- this->SetDirty(ev);
- }
- }
- else // unable to acquire Modal focus
- {
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrEditorModal);
- }
- }
- }
- else // unable to acquire SoundIn focus
- {
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrEditorRecording);
- }
-
- CATCH_ALL
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrCannotRecordSound);
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: StopRecordingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::StopRecordingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","StopRecordingSound");
-
- if ( !fRecorder->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndDeviceNotOpened);
- return;
- }
-
- ODBoolean wasPaused = fRecorder->IsPaused();
-
- if ( fRecorder->Stop() )
- {
- ODFrame* frame = this->FindFirstAvailableFrame(ev);
-
- // Stop checking the status of the sound input device.
-
- fSession->GetDispatcher(ev)->UnregisterIdle(ev, fSelf, frame);
-
- // Save the recorded sound into the player object
- fPlayer->SetSound(fRecorder->GetSound());
-
- fSecsRecorded = fRecorder->GetTime();
- fUnknownSound = kODFalse;
-
- if (fPreferredKind == kODNullTypeToken)
- fPreferredKind = gGlobals->fNativeData;
-
- this->SetDirty(ev);
-
- fSession->GetArbitrator(ev)
- ->RelinquishFocus(ev, gGlobals->fSoundInFocus, frame);
- this->FocusLost(ev, gGlobals->fSoundInFocus, frame);
-
- this->InvalidateButton(ev, kRecordButton);
- this->InvalidateButton(ev, kStopButton);
- this->InvalidateButton(ev, kPauseButton);
- this->InvalidateButton(ev, kPlayButton);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fSpeakerIconRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: PauseRecordingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::PauseRecordingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","PauseRecordingSound");
-
- if ( !fRecorder->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- if ( fRecorder->Pause() )
- this->InvalidateButton(ev, kPauseButton);
- }
-
- //------------------------------------------------------------------------------
- // Method: ResumeRecordingSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::ResumeRecordingSound( Environment* ev )
- {
- SOM_Trace("SoundEditor","ResumeRecordingSound");
-
- if ( !fRecorder->IsInitialized() )
- {
- this->DoDialogBox(ev, kODNULL, kErrorBoxID, kErrSndChannelNotInited);
- return;
- }
-
- if ( fRecorder->Resume() )
- this->InvalidateButton(ev, kPauseButton);
- }
-
- //------------------------------------------------------------------------------
- // Method: SoundDoneRecording
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::SoundDoneRecording( Environment* ev )
- {
- SOM_Trace("SoundEditor","SoundDoneRecording");
-
- if ( !this->SoundRecording() )
- return kODFalse;
-
- return this->UpdateDisplay(ev, fRecorder);
- }
-
- //------------------------------------------------------------------------------
- // Methods: Methods to find out state of editor, and certain
- // information about it
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::SoundPlaying()
- {
- return fPlayer->IsPlaying();
- }
-
- ODBoolean SoundEditor::SoundRecording()
- {
- return fRecorder->IsRecording();
- }
-
- ODBoolean SoundEditor::SoundPaused()
- {
- return fPlayer->IsPaused() || fRecorder->IsPaused();
- }
-
- OSType SoundEditor::GetRecordingQuality()
- {
- return fRecordingQuality;
- }
-
- void SoundEditor::SetRecordingQuality(OSType rQuality)
- {
- if ( rQuality != fRecordingQuality )
- {
- Environment* ev = somGetGlobalEnvironment();
-
- fRecordingQuality = rQuality;
- fMaxSeconds = fRecorder->GetMaxTime(fMaxMemory, fRecordingQuality);
-
- this->InvalidateFrameViewRect(ev, gGlobals->fMaxTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
- this->SetDirty(ev);
- }
- }
-
- ODBoolean SoundEditor::GetSoundQuality(OSType* rQuality)
- {
- if (fUnknownSound)
- return kODFalse;
-
- *rQuality = fRecorder->GetQuality();
- return kODTrue;
- }
-
- ODULong SoundEditor::GetCurrentTime()
- {
- return fCurrentTime;
- }
-
- ODULong SoundEditor::GetMaxTime()
- {
- return fMaxSeconds;
- }
-
- ODULong SoundEditor::GetRecordedTime()
- {
- return fSecsRecorded;
- }
-
-
- ODBoolean SoundEditor::IsPlayAvailable()
- {
- return ( fPlayer->HasSound()
- && (!fPlayer->IsPlaying() || fPlayer->IsPaused())
- && !fRecorder->IsRecording() );
- }
-
- ODBoolean SoundEditor::IsPauseAvailable()
- {
- return ( fPlayer->IsPlaying() || fRecorder->IsRecording() );
- }
-
- ODBoolean SoundEditor::IsStopAvailable()
- {
- return ( fPlayer->IsPlaying() || fRecorder->IsRecording() );
- }
-
- ODBoolean SoundEditor::IsRecordAvailable()
- {
- return ( (!fRecorder->IsRecording() || fRecorder->IsPaused())
- && !fReadOnlyStorage );
- }
-
-
- //------------------------------------------------------------------------------
- // Method: DrawCurrentTime
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawCurrentTime( Environment* ev,
- ODFacet* facet,
- ODSShort oldTime,
- ODSShort curTime )
- {
- SOM_Trace("SoundEditor","DrawCurrentTime");
-
- if ( curTime < 0 )
- curTime = 0;
-
- if ( oldTime > -1 && oldTime == curTime )
- return;
-
- // Draw the current time
- DrawTime(ev, facet, gGlobals->fCurrentTimeRect, 12, curTime);
- }
-
- //------------------------------------------------------------------------------
- // Method: DrawProgressBar
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawProgressBar( Environment* ev,
- ODFacet* facet,
- ODSShort progress,
- ODSShort pixPatID )
- {
- SOM_Trace("SoundEditor","DrawProgressBar");
-
- if ( progress > 100 )
- progress = 100;
- if ( progress < 0 )
- progress = 0;
-
- ODSShort sizeBar = (gGlobals->fProgressBarRect.right - gGlobals->fProgressBarRect.left)
- * progress / 100;
-
- Rect newBar = gGlobals->fProgressBarRect;
- newBar.right = newBar.left + sizeBar;
-
- {
- CUsingLibraryResources res;
- CFocus initiateDrawing(ev, facet);
-
- PixPatHandle thePat = GetPixPat(pixPatID);
- FillCRect(&newBar, thePat);
- DisposePixPat(thePat);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: CopySound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::CopySound( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","CopySound");
-
- // Acquire clipboard focus
- TempClipboardFocus clipboardFocus(ev, frame);
- if ( clipboardFocus.Request() )
- {
- ODClipboard* clipboard = fSession->GetClipboard(ev);
- clipboard->Clear(ev);
-
- ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
- ODDraft* fromDraft = ODGetDraft(ev, fSelf);
- ODDraft* toDraft = clipboardSU->GetDraft(ev);
- ODDraftKey key = kODNULLKey;
-
- ODVolatile(key);
-
- TRY
- key = fromDraft->BeginClone(ev, toDraft, kODNULL, kODCloneCopy);
-
- // Verify that the properties we want to write into exist.
- this->CheckAndAddProperties(ev, clipboardSU);
-
- // Write out the part's content annotation.
- this->ExternalizeAnnotation(ev, clipboardSU, key, frame);
-
- // Write out the part's content.
- if ( fPreferredKind == gGlobals->fNativeData )
- {
- this->ExternalizeContent(ev, clipboardSU, key, frame, gGlobals->fNativeData);
- this->ExternalizeContent(ev, clipboardSU, key, frame, gGlobals->fMacSndData);
- }
- else if ( fPreferredKind == gGlobals->fMacSndData )
- {
- this->ExternalizeContent(ev, clipboardSU, key, frame, gGlobals->fMacSndData);
- }
- else
- {
- WARN("fPreferredKind is an unknown kind.");
- }
-
- fromDraft->EndClone(ev, key);
- CATCH_ALL
- if ( key != kODNULLKey )
- fromDraft->AbortClone(ev, key);
-
- clipboard->Clear(ev);
- RERAISE;
- ENDTRY
- }
- else
- {
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrCantGetClipboard);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: AnnotateClipboard
- // Origin: SoundEditor
- //
- // Description: This method is called by the part...
- //------------------------------------------------------------------------------
-
- void SoundEditor::AnnotateClipboard( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","AnnotateClipboard");
-
- // Acquire clipboard focus
- TempClipboardFocus clipboardFocus(ev, frame);
- if ( clipboardFocus.Request() )
- {
- ODClipboard* clipboard = fSession->GetClipboard(ev);
- ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
- clipboardSU->AddProperty(ev, kODPropSuggestedFrameShape);
-
- TempODShape frameShape = frame->AcquireFrameShape(ev, kODNULL);
- frameShape->WriteShape(ev, clipboardSU);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: PasteSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::PasteSound( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","PasteSound");
-
- // Acquire clipboard focus
- TempClipboardFocus clipboardFocus(ev, frame);
- if ( clipboardFocus.Request() )
- {
- ODClipboard* clipboard = fSession->GetClipboard(ev);
- ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
-
- // Read in the content annotation.
- this->InternalizeAnnotation(ev, clipboardSU);
-
- // Read in the new sound data.
- this->InternalizeContent(ev, clipboardSU);
-
- this->SetDirty(ev);
-
- this->InvalidateButton(ev, kPlayButton);
-
- // Update Window to reflect changes in contained sound
- this->InvalidateFrameViewRect(ev, gGlobals->fCurrentTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fMaxTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
- }
- else
- {
- this->DoDialogBox(ev, frame, kErrorBoxID, kErrCantGetClipboard);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: ClearSound
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when...
- //------------------------------------------------------------------------------
-
- void SoundEditor::ClearSound( Environment* ev,
- ODFrame* frame )
-
- {
- SOM_Trace("SoundEditor","ClearSound");
-
- // Discard sound seconds recorded
- fPlayer->DisposeSound();
- fSecsRecorded = 0;
-
- this->InvalidateButton(ev, kPlayButton);
-
- // Update Window to reflect changes in contained sound
- this->InvalidateFrameViewRect(ev, gGlobals->fCurrentTimeRect);
- this->InvalidateFrameViewRect(ev, gGlobals->fProgressBarRect);
-
- this->SetDirty(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: SoundOnClipboard
- // Origin: SoundEditor
- //
- // Description: The method is called by the part to deterine if the clipboard
- // contains a sound.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::SoundOnClipboard( Environment* ev,
- ODFrame* frame )
- {
- SOM_Trace("SoundEditor","SoundOnClipboard");
-
- ODBoolean result = kODFalse;
-
- // Acquire clipboard focus
- TempClipboardFocus clipboardFocus(ev, frame);
- if ( clipboardFocus.Request() )
- {
- ODClipboard* clipboard = fSession->GetClipboard(ev);
- ODStorageUnit* clipboardSU = clipboard->GetContentStorageUnit(ev);
-
- result = clipboardSU->Exists(ev, kODPropContents, kSoundEditorKind, 0);
- result |= clipboardSU->Exists(ev, kODPropContents, gGlobals->fSndDataKind, 0);
- }
-
- return result;
- }
-
- //------------------------------------------------------------------------------
- // Method: FindFirstAvailableFrame
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when it needs a frame for
- // some reason (like acquiring a focus), but there is no particular
- // frame that is associated with the action.
- //------------------------------------------------------------------------------
-
- ODFrame* SoundEditor::FindFirstAvailableFrame( Environment* ev )
- {
- ODFrame* frame = kODNULL;
-
- // We need to locate a frame to use for requesting the modal focus.
- // Find the first valid frame in our display frames list.
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- if ( proxy->FrameIsLoaded(ev) )
- frame = proxy->GetFrame(ev);
- if ( frame ) break;
- }
-
- return frame;
- }
-
- //------------------------------------------------------------------------------
- // Method: InvalidateFrameViewRect
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when an area of the part
- // (in frame view or for the controls presentation).
- //------------------------------------------------------------------------------
-
- void SoundEditor::InvalidateFrameViewRect( Environment* ev,
- Rect& bounds )
- {
- ODRect invalidRect;
- IntToFixedRect(bounds, invalidRect);
-
- // Iterate over the frames we are displayed through and determine which
- // ones we need to invalidate.
- CListIterator fiter(fDisplayFrames);
- for ( CFrameProxy* proxy = (CFrameProxy*) fiter.First();
- fiter.IsNotComplete(); proxy = (CFrameProxy*) fiter.Next() )
- {
- // If the display frame is real (has been "connected" or was "added")
- // get its view type; otherwise, ignore it.
- if ( proxy->FrameIsLoaded(ev) )
- {
- ODFrame* frame = proxy->GetFrame(ev);
-
- if ( frame->GetPresentation(ev) == gGlobals->fControlsPresentation
- && frame->GetViewType(ev) == gGlobals->fFrameView )
- {
- TempODShape invalidShape = frame->CreateShape(ev);
- invalidShape->SetRectangle(ev, &invalidRect);
-
- frame->Invalidate(ev, invalidShape, kODNULL);
- }
- }
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: DrawButton
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when a button needs to be
- // drawn.
- //------------------------------------------------------------------------------
-
- void SoundEditor::DrawButton( Environment* ev,
- EButton button,
- EButtonState buttonState )
- {
- ODSShort pictID = kNormalButtonPICT;
- IconTransformType iconTrans = ttNone;
-
- switch (buttonState)
- {
- case kButtonStatePressed:
- pictID = kPressedButtonPICT;
- iconTrans = ttSelected;
- break;
-
- case kButtonStateOn:
- pictID = kOnButtonPICT;
- iconTrans = ttNone;
- break;
-
- case kButtonStateDim:
- pictID = kDimButtonPICT;
- iconTrans = ttDisabled;
- break;
- }
-
- DrawEditorPicture(pictID, gGlobals->fButtonRect[button]);
-
- Rect iconRect = gGlobals->fButtonRect[button];
- iconRect.top += 5;
- iconRect.left += 10;
- iconRect.bottom = iconRect.top + kODSmallIconSize;
- iconRect.right = iconRect.left + kODSmallIconSize;
-
- CUsingLibraryResources res;
- PlotIconID(&iconRect, atNone, iconTrans, kRecordButtonIcon + button);
- }
-
- //------------------------------------------------------------------------------
- // Method: TrackButton
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when a button needs to be
- // tracked because there was a mouse-down in it.
- //------------------------------------------------------------------------------
-
- ODBoolean SoundEditor::TrackButton( Environment* ev,
- EButton button,
- Point where,
- EButtonState initialState )
- {
- ODBoolean isInButton = kODTrue;
- ODBoolean wasInButton = kODFalse;
- Point curLoc = where;
-
- do
- {
- isInButton = PtInRect(curLoc, &gGlobals->fButtonRect[button]);
-
- if (isInButton != wasInButton)
- {
- this->DrawButton(ev, button, isInButton ? kButtonStatePressed
- : initialState);
- wasInButton = isInButton;
- }
-
- GetMouse(&curLoc);
- }
- while (StillDown());
-
- return isInButton;
- }
-
- //------------------------------------------------------------------------------
- // Method: InvalidateButton
- // Origin: SoundEditor
- //
- // Description: The method is called by the part when a button needs to be
- // tracked because there was a mouse-down in it.
- //------------------------------------------------------------------------------
-
- void SoundEditor::InvalidateButton( Environment* ev,
- EButton button )
- {
- this->InvalidateFrameViewRect(ev, gGlobals->fButtonRect[button]);
- }
-
-